Referens till modellinstans¶
Detta dokument beskriver detaljerna i API:et Model. Det bygger på det material som presenteras i guiderna model och database query, så du vill förmodligen läsa och förstå dessa dokument innan du läser det här.
I den här referensen använder vi exempel på bloggmodeller som presenteras i guide för databasfrågor.
Skapa objekt¶
För att skapa en ny instans av en modell instansierar du den som vilken annan Python-klass som helst:
Nyckelordsargumenten är namnen på de fält du har definierat i modellen. Observera att instansiering av en modell inte på något sätt berör databasen; för det behöver du anropa save().
Observera
Du kanske vill anpassa modellen genom att åsidosätta metoden __init__. Om du gör det måste du dock vara noga med att inte ändra anropssignaturen, eftersom en ändring kan hindra modellinstansen från att sparas. Dessutom kan referenser till modellfält i __init__ i vissa situationer orsaka oändliga rekursionsfel. I stället för att åsidosätta __init__, prova något av följande tillvägagångssätt:
Lägg till en classmethod på modellklassen:
from django.db import models class Book(models.Model): title = models.CharField(max_length=100) @classmethod def create(cls, title): book = cls(title=title) # do something with the book return book book = Book.create("Pride and Prejudice")
Lägg till en metod på en anpassad manager (vanligtvis att föredra):
class BookManager(models.Manager): def create_book(self, title): book = self.create(title=title) # do something with the book return book class Book(models.Model): title = models.CharField(max_length=100) objects = BookManager() book = Book.objects.create_book("Pride and Prejudice")
Tilldelning av attribut konverterar inte typer
Att tilldela ett modellattribut konverterar inte värdet till fältets Python-typ. Konverteringen sker när modellen valideras. Även om ett fält som tilldelas ett värde av en annan typ (t.ex. en sträng som tilldelas UUIDField) kan konverteras när save() kör en fråga, behåller instansen i minnet originalvärdet tills den läses in igen.
Anpassning av modellbelastning¶
Metoden from_db() kan användas för att anpassa skapandet av modellinstanser vid laddning från databasen.
Argumentet db innehåller databasaliaset för den databas som modellen läses in från, field_names innehåller namnen på alla inlästa fält och values innehåller de inlästa värdena för varje fält i field_names. field_names har samma ordning som values. Om alla modellens fält finns med garanteras att values har den ordning som __init__() förväntar sig. Det innebär att instansen kan skapas med cls(*values). Om några fält är uppskjutna visas de inte i field_names. Tilldela då värdet django.db.models.DEFERRED till vart och ett av de saknade fälten. Argumentet fetch_mode innehåller hämtningsläget för den fråga som läste in instansen, eller None om den lästes in utanför en fråga.
Utöver att skapa den nya modellen måste metoden from_db() ange flaggorna adding och db i den nya instansens _state-attribut och, när fetch_mode inte är None, dess fetch_mode-attribut.
Nedan följer ett exempel som visar hur man registrerar de ursprungliga värdena för fält som laddas från databasen:
from django.db.models import DEFERRED
@classmethod
def from_db(cls, db, field_names, values, *, fetch_mode=None):
# Default implementation of from_db() (subject to change and could
# be replaced with super()).
if len(values) != len(cls._meta.concrete_fields):
values = list(values)
values.reverse()
values = [
values.pop() if f.attname in field_names else DEFERRED
for f in cls._meta.concrete_fields
]
instance = cls(*values)
instance._state.adding = False
instance._state.db = db
if fetch_mode is not None:
instance._state.fetch_mode = fetch_mode
# customization to store the original field values on the instance
instance._loaded_values = dict(
zip(field_names, (value for value in values if value is not DEFERRED))
)
return instance
def save(self, **kwargs):
# Check how the current values differ from ._loaded_values. For example,
# prevent changing the creator_id of the model. (This example doesn't
# support cases where 'creator_id' is deferred).
if not self._state.adding and (
self.creator_id != self._loaded_values["creator_id"]
):
raise ValueError("Updating the value of creator isn't allowed")
super().save(**kwargs)
Exemplet ovan visar en fullständig from_db()-implementering för att klargöra hur det görs. I det här fallet skulle det vara möjligt att använda ett super()-anrop i from_db()-metoden.
Parametern fetch_mode lades till.
Ersatt sedan version 6.1: Support for from_db() methods that do not accept the fetch_mode
keyword argument is deprecated and will be removed in Django 2028.
Uppdatering av objekt från databas¶
Om du tar bort ett fält från en modellinstans laddas värdet från databasen när du öppnar det igen:
>>> obj = MyModel.objects.first()
>>> del obj.field
>>> obj.field # Loads the field from the database
- Model.arefresh_from_db(using=None, fields=None, from_queryset=None)¶
Asynkron version: arefresh_from_db()
Om du behöver ladda om en modells värden från databasen kan du använda metoden refresh_from_db(). När denna metod anropas utan argument görs följande:
Alla icke uppskjutna fält i modellen uppdateras till de värden som för närvarande finns i databasen.
Alla cachelagrade relationer rensas från den omladdade instansen.
Endast modellens fält laddas om från databasen. Andra databasberoende värden som t.ex. annoteringar laddas inte om. Eventuella @cached_property-attribut rensas inte heller.
Omladdningen sker från den databas som instansen laddades från, eller från standarddatabasen om instansen inte laddades från databasen. Argumentet using kan användas för att tvinga fram den databas som används för omlastning.
Det är möjligt att tvinga fram en uppsättning fält som ska laddas genom att använda argumentet fields.
Om du till exempel vill testa att ett anrop av update() resulterar i den förväntade uppdateringen, kan du skriva ett test som liknar detta:
def test_update_result(self):
obj = MyModel.objects.create(val=1)
MyModel.objects.filter(pk=obj.pk).update(val=F("val") + 1)
# At this point obj.val is still 1, but the value in the database
# was updated to 2. The object's updated value needs to be reloaded
# from the database.
obj.refresh_from_db()
self.assertEqual(obj.val, 2)
När ett uppskjutet fält läses in vid behov för en enskild modellinstans sker inläsningen genom den här metoden. Det går därför att anpassa hur inläsningen sker. Exemplet nedan visar hur man kan läsa in alla instansens fält på nytt när ett uppskjutet fält läses in vid behov:
class ExampleModel(models.Model):
def refresh_from_db(self, using=None, fields=None, **kwargs):
# fields contains the name of the deferred field to be
# loaded.
if fields is not None:
fields = set(fields)
deferred_fields = self.get_deferred_fields()
# If any deferred field is going to be loaded
if fields.intersection(deferred_fields):
# then load all of them
fields = fields.union(deferred_fields)
super().refresh_from_db(using, fields, **kwargs)
Argumentet from_queryset gör det möjligt att använda en annan queryset än den som skapats från _base_manager. Det ger dig mer kontroll över hur modellen laddas om. Till exempel:, när din modell använder soft deletion kan du göra refresh_from_db() för att ta hänsyn till detta:
obj.refresh_from_db(from_queryset=MyModel.active_objects.all())
Du kan cacha relaterade objekt som annars skulle rensas bort från den omladdade instansen:
obj.refresh_from_db(from_queryset=MyModel.objects.select_related("related_field"))
Du kan låsa raden till slutet av transaktionen innan du laddar om en modells värden:
obj.refresh_from_db(from_queryset=MyModel.objects.select_for_update())
En hjälpmetod som returnerar en uppsättning som innehåller attributnamnen för alla de fält som för närvarande är uppskjutna för denna modell.
Validering av objekt¶
Det finns fyra steg i valideringen av en modell:
Validera modellfälten –
Model.clean_fields()Validera modellen som helhet –
Model.clean()Validera fältens unikhet –
Model.validate_unique()Validera begränsningarna -
Model.validate_constraints()
Alla fyra stegen utförs när du anropar en modells full_clean()-metod.
När du använder en ModelForm utför anropet till is_valid() dessa valideringssteg för alla fält som ingår i formuläret. Mer information finns i ModelForm-dokumentationen. Du bör bara behöva anropa modellens full_clean()-metod om du tänker hantera valideringsfel själv eller om du har uteslutit fält från ModelForm som kräver validering.
Metoden anropar Model.clean_fields(), Model.clean(), Model.validate_unique() (om validate_unique är True) och Model.validate_constraints() (om validate_constraints är True) i den ordningen och utlöser en ValidationError som har attributet message_dict med fel från alla fyra steg.
Det valfria argumentet exclude kan användas för att tillhandahålla en uppsättning av fältnamn som kan uteslutas från validering och rengöring. ModelForm använder detta argument för att utesluta fält som inte finns i ditt formulär från att valideras eftersom eventuella fel som uppstår inte kan korrigeras av användaren.
Observera att full_clean() inte anropas automatiskt när du anropar modellens save()-metod. Du måste anropa den manuellt när du vill köra modellvalidering på en gång för egna manuellt skapade modeller. Till exempel:
from django.core.exceptions import ValidationError
try:
article.full_clean()
except ValidationError as e:
# Do something based on the errors contained in e.message_dict.
# Display them to a user, or handle them programmatically.
pass
Det första steget som full_clean() utför är att rengöra varje enskilt fält.
Denna metod validerar alla fält i din modell. Det valfria exclude argumentet låter dig tillhandahålla en uppsättning av fältnamn som ska uteslutas från validering. Det kommer att ge upphov till en ValidationError om några fält misslyckas med valideringen.
Det andra steg som full_clean() utför är att anropa Model.clean(). Den här metoden bör åsidosättas för att utföra anpassad validering i modellen.
Den här metoden bör användas för att tillhandahålla anpassad modellvalidering och för att ändra attribut på din modell om så önskas. Du kan t.ex. använda den för att automatiskt ange ett värde för ett fält eller för att göra en validering som kräver åtkomst till mer än ett enda fält:
import datetime
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import gettext_lazy as _
class Article(models.Model):
...
def clean(self):
# Don't allow draft entries to have a pub_date.
if self.status == "draft" and self.pub_date is not None:
raise ValidationError(_("Draft entries may not have a publication date."))
# Set the pub_date for published items if it hasn't been set already.
if self.status == "published" and self.pub_date is None:
self.pub_date = datetime.date.today()
Observera dock att en modells clean()-metod, liksom Model.full_clean(), inte anropas när du anropar modellens save()-metod.
I exemplet ovan instantierades undantaget ValidationError av Model.clean() med en sträng, så det kommer att lagras i en speciell felordboksnyckel, NON_FIELD_ERRORS. Den här nyckeln används för fel som är knutna till hela modellen istället för till ett specifikt fält:
from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
try:
article.full_clean()
except ValidationError as e:
non_field_errors = e.message_dict[NON_FIELD_ERRORS]
För att tilldela undantag till ett specifikt fält, instansiera ValidationError med en ordbok, där nycklarna är fältnamnen. Vi kan uppdatera det föregående exemplet för att tilldela felet till fältet pub_date:
class Article(models.Model):
...
def clean(self):
# Don't allow draft entries to have a pub_date.
if self.status == "draft" and self.pub_date is not None:
raise ValidationError(
{"pub_date": _("Draft entries may not have a publication date.")}
)
...
Om du upptäcker fel i flera fält under Model.clean() kan du också skicka en ordlista som mappar fältnamn till errors:
raise ValidationError(
{
"title": ValidationError(_("Missing title."), code="required"),
"pub_date": ValidationError(_("Invalid date."), code="invalid"),
}
)
Sedan kommer full_clean() att kontrollera unika begränsningar för din modell.
Så här skapar du fältspecifika valideringsfel om dessa fält inte visas i ett ModelForm
Du kan inte skapa valideringsfel i Model.clean() för fält som inte visas i ett modellformulär (ett formulär kan begränsa sina fält med hjälp av Meta.fields eller Meta.exclude). Om du gör det kommer ett ValueError att uppstå eftersom valideringsfelet inte kommer att kunna associeras med det uteslutna fältet.
För att komma runt detta dilemma, åsidosätt istället Model.clean_fields() eftersom den tar emot listan över fält som är undantagna från validering. Till exempel:
class Article(models.Model):
...
def clean_fields(self, exclude=None):
super().clean_fields(exclude=exclude)
if self.status == "draft" and self.pub_date is not None:
if exclude and "status" in exclude:
raise ValidationError(
_("Draft entries may not have a publication date.")
)
else:
raise ValidationError(
{
"status": _(
"Set status to draft if there is not a publication date."
),
}
)
Denna metod liknar clean_fields(), men validerar unikhetsbegränsningar som definieras via Field.unique, Field.unique_for_date, Field.unique_for_month, Field.unique_for_year eller Meta.unique_together på din modell istället för enskilda fältvärden. Det valfria argumentet exclude låter dig tillhandahålla en uppsättning av fältnamn som ska uteslutas från validering. Det kommer att ge upphov till en ValidationError om några fält misslyckas med valideringen.
UniqueConstraints som definieras i Meta.constraints valideras av Model.validate_constraints().
Observera att om du anger ett exclude-argument till validate_unique(), kommer alla unique_together-begränsningar som involverar ett av de fält du angav inte att kontrolleras.
Slutligen kommer full_clean() att kontrollera eventuella andra begränsningar för din modell.
Denna metod validerar alla begränsningar som definieras i Meta.constraints. Det valfria exclude-argumentet låter dig tillhandahålla en uppsättning av fältnamn som ska uteslutas från validering. Det kommer att ge upphov till en ValidationError om några begränsningar misslyckas med valideringen.
Spara objekt¶
För att spara ett objekt tillbaka till databasen, anropa save():
- Model.save(*, force_insert=False, force_update=False, using=DEFAULT_DB_ALIAS, update_fields=None)[source]¶
- Model.asave(*, force_insert=False, force_update=False, using=DEFAULT_DB_ALIAS, update_fields=None)¶
Asynkron version: asave()
Mer information om hur du använder argumenten force_insert och force_update finns i Tvinga fram en INSERT eller UPDATE. Detaljer om argumentet update_fields finns i avsnittet Ange vilka fält som ska sparas.
Om du vill ha ett anpassat sparbeteende kan du åsidosätta denna metod save(). Se Åsidosätta fördefinierade modellmetoder för mer information.
Processen för att spara modeller har också vissa finesser; se avsnitten nedan.
Automatiskt ökande primärnycklar¶
Om en modell har en AutoField - en automatiskt ökande primärnyckel - kommer det automatiskt ökande värdet att beräknas och sparas som ett attribut på ditt objekt första gången du anropar save():
>>> b2 = Blog(name="Cheddar Talk", tagline="Thoughts on cheese.")
>>> b2.id # Returns None, because b2 doesn't have an ID yet.
>>> b2.save()
>>> b2.id # Returns the ID of your new object.
Det finns inget sätt att säga vad värdet på ett ID kommer att vara innan du anropar save(), eftersom det värdet beräknas av din databas, inte av Django.
För enkelhetens skull har varje modell en AutoField med namnet id som standard om du inte uttryckligen anger primary_key=True på ett fält i din modell. Se dokumentationen för AutoField för mer information.
Egenskapen ”pk¶
- Model.pk¶
Oavsett om du definierar ett primärnyckelfält själv, eller låter Django leverera ett åt dig, kommer varje modell att ha en egenskap som heter pk. Den beter sig som ett vanligt attribut på modellen, men är faktiskt ett alias för vilket fält eller fält som utgör primärnyckeln för modellen. Du kan läsa och ställa in det här värdet, precis som du skulle göra för vilket annat attribut som helst, och det kommer att uppdatera rätt fält i modellen.
Explicit specificering av värden för auto-primary-key¶
Om en modell har en AutoField men du vill definiera ett nytt objekts ID uttryckligen när du sparar, definierar du det uttryckligen innan du sparar, i stället för att förlita dig på den automatiska tilldelningen av ID:
>>> b3 = Blog(id=3, name="Cheddar Talk", tagline="Thoughts on cheese.")
>>> b3.id # Returns 3.
>>> b3.save()
>>> b3.id # Returns 3.
Om du tilldelar auto-primary-key-värden manuellt, se till att inte använda ett redan existerande primary-key-värde! Om du skapar ett nytt objekt med ett explicit primary-key-värde som redan finns i databasen, kommer Django att anta att du ändrar den befintliga posten snarare än att skapa en ny.
Med tanke på bloggexemplet ”Cheddar Talk” ovan skulle detta exempel åsidosätta den föregående posten i databasen:
b4 = Blog(id=3, name="Not Cheddar", tagline="Anything but cheese.")
b4.save() # Overrides the previous blog with ID=3!
Se Hur Django vet att UPDATE vs. INSERT, nedan, för anledningen till att detta händer.
Att uttryckligen ange värden för automatisk primärnyckel är mest användbart för masslagring av objekt, när du är säker på att du inte kommer att få kollisioner mellan primärnycklar.
Om du använder PostgreSQL kan sekvensen som är associerad med den primära nyckeln behöva uppdateras; se Manuellt specificerade värden för primärnycklar med automatisk inkrementering.
Vad händer när du sparar?¶
När du sparar ett objekt utför Django följande steg:
**Sänd en signal före sparande
pre_save-signalen skickas, vilket gör att alla funktioner som lyssnar på den signalen kan göra något.**Varje fälts metod
pre_save()anropas för att utföra alla automatiserade datamodifieringar som behövs. Till exempel: åsidosätter datum-/tidsfältenpre_save()för att implementeraauto_now_addochauto_now.**Varje fälts
get_db_prep_save()-metod ombeds att tillhandahålla sitt aktuella värde i en datatyp som kan skrivas till databasen.De flesta fält kräver ingen dataförberedelse. Enkla datatyper, t.ex. heltal och strängar, är ”skrivklara” som Python-objekt. Mer komplexa datatyper kräver dock ofta viss modifiering.
Till exempel: använder
DateField-fält ett Python-objekt meddatetimeför att lagra data. Databaser lagrar intedatetime-objekt, så fältvärdet måste konverteras till en ISO-kompatibel datumsträng för att infogas i databasen.**De förbehandlade, förberedda uppgifterna sammanställs till en SQL-sats för inmatning i databasen.
**Skicka en post-save-signal
post_save-signalen skickas, vilket gör att alla funktioner som lyssnar på den signalen kan göra något.
Hur Django vet att UPDATE vs. INSERT¶
Du kanske har märkt att Djangos databasobjekt använder samma save()-metod för att skapa och ändra objekt. Django abstraherar behovet av att använda INSERT eller UPDATE SQL-satser. När du anropar save() och objektets primära nyckelattribut inte definierar en default eller db_default, följer Django denna algoritm:
Om objektets primära nyckelattribut är inställt på något annat än
None, utför Django enUPDATE.Om objektets primärnyckelattribut inte är inställt eller om
UPDATEinte uppdaterade någonting (t.ex. om primärnyckeln är inställd på ett värde som inte finns i databasen), utför Django enINSERT.
Om objektets primära nyckelattribut definierar en default eller db_default så utför Django en UPDATE om det är en befintlig modellinstans och den primära nyckeln är inställd på ett värde som finns i databasen. Annars utför Django en INSERT.
Det enda problemet här är att du bör vara försiktig så att du inte uttryckligen anger ett primärnyckelvärde när du sparar nya objekt, om du inte kan garantera att primärnyckelvärdet är oanvänt. För mer information om denna nyans, se Explicit specificering av auto-primary-key-värden ovan och Tvinga fram en INSERT eller UPDATE nedan.
I Django 1.5 och tidigare gjorde Django en SELECT när primärnyckelattributet var inställt. Om SELECT hittade en rad, gjorde Django en UPDATE, annars gjorde den en INSERT. Den gamla algoritmen resulterar i ytterligare en fråga i fallet UPDATE. Det finns några sällsynta fall där databasen inte rapporterar att en rad uppdaterades även om databasen innehåller en rad för objektets primära nyckelvärde. Ett exempel är PostgreSQL ON UPDATE trigger som returnerar NULL. I sådana fall är det möjligt att återgå till den gamla algoritmen genom att ställa in alternativet select_on_save till True.
Tvinga fram en INSERT eller UPDATE¶
I vissa sällsynta situationer behöver du kunna tvinga metoden save() att utföra en SQL-sats INSERT och inte falla tillbaka till UPDATE. Eller tvärtom: uppdatera om möjligt, men infoga inte en ny rad. I dessa fall kan du skicka parametrarna force_insert=True eller force_update=True till metoden save(). Att skicka båda parametrarna är ett fel: du kan inte både infoga och uppdatera samtidigt!
När du använder multi-table inheritance är det också möjligt att tillhandahålla en tupel av överordnade klasser till force_insert för att tvinga fram INSERT-satser för varje bas. Till exempel:
Restaurant(pk=1, name="Bob's Cafe").save(force_insert=(Place,))
Restaurant(pk=1, name="Bob's Cafe", rating=4).save(force_insert=(Place, Rating))
Du kan skicka force_insert=(models.Model,) för att tvinga fram en INSERT-sats för alla föräldrar. Som standard tvingar force_insert=True bara fram en ny rad för den aktuella modellen.
När en tvingad uppdatering inte påverkar några rader utlöses undantaget NotUpdated. I tidigare versioner utlöstes det generella undantaget django.db.DatabaseError.
Det bör vara mycket sällsynt att du behöver använda dessa parametrar. Django kommer nästan alltid att göra det rätta och att försöka åsidosätta det kommer att leda till fel som är svåra att spåra. Denna funktion är endast avsedd för avancerad användning.
Om du använder update_fields kommer du att tvinga fram en uppdatering på samma sätt som force_update.
Uppdatering av attribut baserat på befintliga fält¶
Ibland behöver du utföra en enkel aritmetisk uppgift på ett fält, till exempel att öka eller minska det aktuella värdet. Ett sätt att uppnå detta är att göra aritmetiken i Python som:
>>> product = Product.objects.get(name="Venezuelan Beaver Cheese")
>>> product.number_sold += 1
>>> product.save()
Om det gamla värdet för number_sold som hämtades från databasen var 10, kommer värdet 11 att skrivas tillbaka till databasen.
Processen kan göras robust, genom att undvika ett konkurrensvillkor, och något snabbare genom att uttrycka uppdateringen relativt fältets ursprungliga värde i stället för som en explicit tilldelning av ett nytt värde. Django tillhandahåller F-uttryck för att utföra den här typen av relativ uppdatering. Med F-uttryck uttrycks föregående exempel så här:
>>> from django.db.models import F
>>> product = Product.objects.get(name="Venezuelan Beaver Cheese")
>>> product.number_sold = F("number_sold") + 1
>>> product.save()
Mer information finns i dokumentationen om F-uttryck och deras användning i uppdateringsfrågor.
Ange vilka fält som ska sparas¶
Om save() får en lista med fältnamn i nyckelordsargumentet update_fields, kommer endast de fält som anges i listan att uppdateras. Detta kan vara önskvärt om du bara vill uppdatera ett eller ett fåtal fält på ett objekt. Det finns en liten prestandafördel med att förhindra att alla modellfält uppdateras i databasen. Till exempel:
product.name = "Name changed again"
product.save(update_fields=["name"])
Argumentet update_fields kan vara en iterabel som innehåller strängar. En tom update_fields iterabel hoppar över sparandet. Ett värde av None kommer att utföra en uppdatering på alla fält.
Om du anger update_fields kommer du att tvinga fram en uppdatering.
När en modell som hämtats genom uppskjuten modellinläsning (only() eller defer()) sparas uppdateras bara de fält som lästes in från databasen. I praktiken finns då ett automatiskt update_fields. Om du tilldelar eller ändrar värdet för något uppskjutet fält läggs fältet till bland de uppdaterade fälten.
Field.pre_save() och update_fields
Om update_fields skickas in anropas endast pre_save()-metoderna i update_fields. Detta innebär till exempel att datum-/tidsfält med auto_now=True inte kommer att uppdateras om de inte ingår i update_fields.
Radering av objekt¶
- Model.adelete(using=DEFAULT_DB_ALIAS, keep_parents=False)¶
Asynkron version: adelete()
Utfärdar ett SQL-kommando DELETE för objektet. Det tar endast bort objektet i databasen; Python-instansen finns fortfarande kvar och har fortfarande data i sina fält, förutom att primärnyckeln sätts till None. Metoden returnerar antalet borttagna objekt och en ordbok med antalet borttagningar per objekttyp. Returvärdet räknar instanser från relaterade modeller om Django emulerar kaskadbeteende via Python-varianter av on_delete. Annars rapporterar returvärdet för databasvarianter som DB_CASCADE endast instanser av modellen i QuerySet.
Mer information, bland annat om hur du tar bort objekt i bulk, finns i Radering av objekt.
Om du vill ha ett anpassat borttagningsbeteende kan du åsidosätta metoden delete(). Se Åsidosätta fördefinierade modellmetoder för mer information.
Ibland med multi-table inheritance kan du vilja radera endast en underordnad modells data. Om du anger keep_parents=True behålls föräldramodellens data.
Stöd för DB_*-varianterna av attributet on_delete lades till.
Betning av föremål¶
När du pickle en modell, är dess nuvarande tillstånd pickled. När du plockar upp den kommer den att innehålla modellinstansen vid den tidpunkt då den plockades upp, snarare än de data som för närvarande finns i databasen.
Andra metoder för modellinstans¶
Några objektmetoder har speciella syften.
__str__()¶
Metoden __str__() anropas när du anropar str() på ett objekt. Django använder str(obj) på ett antal ställen. Framför allt för att visa ett objekt på Django-adminsidan och som det värde som infogas i en mall när den visar ett objekt. Därför bör du alltid returnera en trevlig, mänskligt läsbar representation av modellen från metoden __str__().
Till exempel:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
def __str__(self):
return f"{self.first_name} {self.last_name}"
__eq__()¶
Metoden equality är definierad så att instanser med samma primära nyckelvärde och samma konkreta klass anses vara lika, förutom att instanser med ett primärt nyckelvärde på None inte är lika med något annat än sig själva. För proxymodeller definieras den konkreta klassen som modellens första icke-proxyförälder; för alla andra modeller är det helt enkelt modellens klass.
Till exempel:
from django.db import models
class MyModel(models.Model):
id = models.AutoField(primary_key=True)
class MyProxyModel(MyModel):
class Meta:
proxy = True
class MultitableInherited(MyModel):
pass
# Primary keys compared
MyModel(id=1) == MyModel(id=1)
MyModel(id=1) != MyModel(id=2)
# Primary keys are None
MyModel(id=None) != MyModel(id=None)
# Same instance
instance = MyModel(id=None)
instance == instance
# Proxy model
MyModel(id=1) == MyProxyModel(id=1)
# Multi-table inheritance
MyModel(id=1) != MultitableInherited(id=1)
__hash__()¶
Metoden __hash__() baseras på instansens primärnyckelvärde. I praktiken är den hash(obj.pk). Om instansen saknar ett primärnyckelvärde utlöses ett TypeError (annars skulle metoden __hash__() returnera olika värden före och efter att instansen sparats), men det är förbjudet i Python att ändra en instans __hash__()-värde.
get_absolute_url()¶
- Model.get_absolute_url()¶
Definiera en get_absolute_url()-metod för att tala om för Django hur man beräknar den kanoniska URL:en för ett objekt. För anropare bör denna metod se ut att returnera en sträng som kan användas för att hänvisa till objektet via HTTP.
Till exempel:
def get_absolute_url(self):
return "/people/%i/" % self.id
Även om den här koden är korrekt och enkel är den kanske inte det mest portabla sättet att skriva den här typen av metod. Funktionen reverse() är vanligtvis det bästa tillvägagångssättet.
Till exempel:
def get_absolute_url(self):
from django.urls import reverse
return reverse("people-detail", kwargs={"pk": self.pk})
En plats där Django använder get_absolute_url() är i admin-appen. Om ett objekt definierar den här metoden kommer objektredigeringssidan att ha en ”Visa på webbplatsen”-länk som hoppar direkt till objektets offentliga vy, som ges av get_absolute_url().
På samma sätt använder ett par andra delar av Django, till exempel syndication feed framework, get_absolute_url() när det är definierat. Om det är vettigt för din modells instanser att var och en har en unik URL, bör du definiera get_absolute_url().
Varning
Du bör undvika att bygga URL:en från obekräftad användarinmatning, för att minska risken för förgiftning av länkar eller omdirigeringar:
def get_absolute_url(self):
return "/%s/" % self.name
Om self.name är '/example.com' returneras '//example.com/', vilket i sin tur är en giltig schemarelativ URL men inte den förväntade '/%2Fexample.com/'.
Det är god praxis att använda get_absolute_url() i mallar i stället för att hårdkoda objektens URL:er. Följande mallkod är till exempel dålig:
<!-- BAD template code. Avoid! -->
<a href="/people/{{ object.id }}/">{{ object.name }}</a>
Den här mallkoden är mycket bättre:
<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>
Logiken här är att om du ändrar URL-strukturen för dina objekt, även för något litet som att korrigera ett stavfel, vill du inte behöva spåra varje plats där URL kan skapas. Specificera den en gång, i get_absolute_url() och låt all din övriga kod anropa den enda platsen.
Observera
Den sträng du returnerar från get_absolute_url() måste endast innehålla ASCII-tecken (krävs enligt URI-specifikationen, RFC 3986 Section 2) och vara URL-kodad, om nödvändigt.
Kod och mallar som anropar get_absolute_url() bör kunna använda resultatet direkt utan någon ytterligare bearbetning. Du kanske vill använda funktionen django.utils.encoding.iri_to_uri() för att hjälpa till med detta om du använder strängar som innehåller tecken utanför ASCII-området.
Extra instansmetoder¶
Utöver save() och delete() kan ett modellobjekt ha några av följande metoder:
- Model.get_FOO_display()¶
För varje fält som har choices inställt, kommer objektet att ha en get_FOO_display() metod, där FOO är namnet på fältet. Denna metod returnerar det ”mänskligt läsbara” värdet för fältet.
Till exempel:
from django.db import models
class Person(models.Model):
SHIRT_SIZES = {
"S": "Small",
"M": "Medium",
"L": "Large",
}
name = models.CharField(max_length=60)
shirt_size = models.CharField(max_length=2, choices=SHIRT_SIZES)
>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display()
'Large'
- Model.get_next_by_FOO(**kwargs)¶
- Model.get_previous_by_FOO(**kwargs)¶
För varje DateField och DateTimeField som inte har null=True, kommer objektet att ha get_next_by_FOO() och get_previous_by_FOO() metoder, där FOO är namnet på fältet. Detta returnerar nästa och föregående objekt med avseende på datumfältet och ger upphov till ett DoesNotExist-undantag när det är lämpligt.
Båda dessa metoder kommer att utföra sina frågor med hjälp av standardhanteraren för modellen. Om du behöver emulera filtrering som används av en anpassad hanterare, eller vill utföra enstaka anpassad filtrering, accepterar båda metoderna också valfria nyckelordsargument, som bör vara i det format som beskrivs i Field lookups.
Observera att om datumvärdena är identiska kommer dessa metoder att använda primärnyckeln som utslagsgivande. Detta garanterar att inga poster hoppas över eller dupliceras. Det innebär också att du inte kan använda dessa metoder på osparade objekt.
Åsidosättande av extra instansmetoder
I de flesta fall bör åsidosättande eller arv av get_FOO_display(), get_next_by_FOO() och get_previous_by_FOO() fungera som förväntat. Eftersom de läggs till av metaklassen är det dock inte praktiskt möjligt att ta hänsyn till alla möjliga arvsstrukturer. I mer komplexa fall bör du åsidosätta Field.contribute_to_class() för att ställa in de metoder du behöver.
Övriga attribut¶
_stat¶
- Model._state¶
Attributet
_statehänvisar till ettModelState-objekt som spårar modellinstansens livscykel.Objektet
ModelStatehar tre attribut:adding, en flagga som ärTrueom modellen ännu inte har sparats i databasen,db, en sträng som hänvisar till databasaliaset som instansen lästes in från eller sparades till, ochfetch_mode, det hämtningsläge som ska användas vid efterföljande fälthämtningar.Nya instanser har
adding=Trueochdb=Noneeftersom de ännu inte har sparats, samtfetch_mode=models.FETCH_ONE. Instanser som hämtas från enQuerySetharadding=False,dbinställt på aliaset för den associerade databasen ochfetch_modekopierat från frågeuppsättningens hämtningsläge.Changed in Django 6.1:Attributet
fetch_modelades till.
_is_pk_set()¶
- Model._is_pk_set()[source]¶
Metoden
_is_pk_set()returnerar om modellinstansenspkär angiven. Den abstraherar modellens definition av primärnyckel och säkerställer konsekvent beteende oberoende av den specifikapk-konfigurationen. EttDatabaseDefaulti en osparad instans betraktas som ej angivet.Changed in Django 6.1:I tidigare versioner returnerades
TrueförDatabaseDefault-värden.