I'm trying to get an abstract model working in Django and I hit a brick wall trying to set the related_name per the recommendation here: http://docs.djangoproject.com/en/dev/topics/db/models/#be-careful-with-related-name
This is what my abstract model looks like:
class CommonModel(models.Model):
created_on = models.DateTimeField(editable=False)
creared_by = models.ForeignKey(User, related_name="%(app_label)s_%(class)s_created", editable=False)
updated_on = models.DateTimeField(editable=False)
updated_by = models.ForeignKey(User, related_name="%(app_label)s_%(class)s_updated", editable=False)
def save(self):
if not self.id:
self.created_on = datetime.now()
self.created_by = user.id
self.updated_on = datetime.now()
self.updated_by = user.id
super(CommonModel, self).save()
class Meta:
abstract = True
My common model is in [project_root]/models.py. It is the parent object of this model, which is located in an app called Feedback [project_root]/feedback/models.py:
from django.db import models
from mediasharks.models import CommonModel
class Feedback(CommonModel):
message = models.CharField(max_length=255)
request_uri = models.CharField(max_length=255)
domain = models.CharField(max_length=255)
feedback_type = models.IntegerField()
Basically I'm trying to set up a common model so that I'll always be able to tell when and by whom database entries were created.
When I run "python manage.py validate" I get this error message: KeyError: 'app_label'
Am I missing something here?
Note the bold text on your link: "Changed in development version". If you're not using a recent checkout of Django trunk - for instance, you're on the latest released version, 1.1 - you should be using this link for the documentation. That version of the text makes no reference to app_label, because it had not yet been introduced.
Related
I've got a Django application with djongo as a database driver. The models are:
class Blog(models.Model):
_id = models.ObjectIdField()
name = models.CharField(max_length=100, db_column="Name")
tagline = models.TextField()
class Entry(models.Model):
_id = models.ObjectIdField()
blog = models.EmbeddedField(
model_container=Blog
)
When I run this application, I got an error:
File "\.venv\lib\site-packages\djongo\models\fields.py", line 125, in _validate_container
raise ValidationError(
django.core.exceptions.ValidationError: ['Field "m.Blog.name" of model container:"<class \'project.m.models.Blog\'>" cannot be named as "name", different from column name "Name"']
I want to keep the name of the field name in my model and database different because the database already exists, and I can't change it. The database uses camelCase for naming fields, whereas in the application, I want to use snake_case.
How to avoid this error?
The error you're getting is due to Djongo trying to validate the field name as in the model and Name as created in the database.
You can specify for Djongo to not validate the fields of the model container by setting validate=False in the EmbeddedField.
Modify your Entry model as:
class Entry(models.Model):
_id = models.ObjectIdField()
blog = models.EmbeddedField(
model_container=Blog, validate=False
)
This should fix your error.
you might need to do manage.py makemigrations and manage.py migrate
try this:
class Blog(models.Model):
_id = models.ObjectIdField()
name = models.CharField(max_length=100, db_column="BlogName")
tagline = models.TextField()
or this
class Blog(models.Model):
_id = models.ObjectIdField()
BlogName = models.CharField(max_length=100, db_column="name")
tagline = models.TextField()
When you use the "db_colum" parameter, you must choose a different name, even if it is lowercase or uppercase
I think it should be db_column instead of bd_column so:
class Blog(models.Model):
_id = models.ObjectIdField()
name = models.CharField(max_length=100, db_column="Name")
tagline = models.TextField()
in a django project i' ve multiple apps, and the common contains the following models:
class CLDate(models.Model):
class Meta:
abstract = True
active = models.BooleanField(default=True)
last_modified = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
class Switch(CLDate):
name = models.CharField(max_length=64)
code = models.CharField(max_length=64, blank=True, null=True)
description = models.TextField(blank=True, null=True)
sorted = models.IntegerField(default=0)
class Currency(Switch):
pass
In another application i import the Switch, and try to add a ForeignKey to a model which inherits also from Switch
class Country(Switch):
...
currency = models.ForeignKey(Currency, on_delete=models.CASCADE)
...
.
Running makemigration or anything with manage.py i get the following error:
SystemCheckError: System check identified some issues:
ERRORS:
ads.Country.currency: (models.E006) The field 'currency' clashes with the
field 'currency' from model 'common.switch'.
Why do i get this error, and how could i resolve it? I mean, at the database level it should be only a "pointer" to the currency Model / object, and should be irrelevant to its type. Of course if i change the inheritance type of the Currency to something else, it works fine.
Django: 2.2
python: 3.5.3
.
I am building a web app, where each product has its own "Profile". I need to add to the model some kind of field where i can add "Comments", with date and text, for keeping track of info such as change in formula, change of provider, change in price, etc.
Any ideas?
models.py
from django.db import models
# Create your models here.
class Horse(models.Model):
name = models.CharField(max_length=255)
nacimiento = models.DateField(blank=True, null=True)
nro = models.IntegerField()
event = models.TextField()
slug = models.SlugField(unique=True)
def __str__(self):
return '%s-%s' % (self.name, self.nro)
So for every event that happens, i need a new entrance with the description provided in the text field.
class HorseTracker(models.Model):
horse = models.ForeignKey(Horse, on_delete=models.CASCADE, related_name='horse')
comment = models.CharField(max_length=128)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created_at']
Each time you change something in your model you can create new instance of HorseTracker with description of changes you've made.
To make it more usefull you can use TabularInline in your HorseAdmin
class HorseTrackerInline(admin.TabularInline):
model = HorseTracker
class HorseAdmin(admin.ModelAdmin):
list_display = ['name', 'nacimiento', 'nro', 'event', 'slug', ]
inlines = [ HorseTrackerInline, ]
If you want to track various models I would suggest to use something like django-simple-history to keep track of the changes in your model.
Adding a history field to the model lets you save all the changes made to the fields and then access the history. If you want to add a custom message you can add fields to the historical model, and in a signal set the message.
from simple_history.models import HistoricalRecords
class MessageHistoricalModel(models.Model):
"""
Abstract model for history models tracking custom message.
"""
message = models.TextField(blank=True, null=True)
class Meta:
abstract = True
class Horse(models.Model):
name = models.CharField(max_length=255)
birthdate = models.DateField(blank=True, null=True)
nro = models.IntegerField()
event = models.TextField()
slug = models.SlugField(unique=True)
history = HistoricalRecords(bases=[MessageHistoricalModel,])
Then using signals you can get changes using diff and then save a custom message stating the changes an who made them.
from django.dispatch import receiver
from simple_history.signals import (post_create_historical_record)
#receiver(post_create_historical_record)
def post_create_historical_record_callback(sender, **kwargs):
history_instance = kwargs['history_instance'] # the historical record created
# <use diff to get the changed fields and create the message>
history_instance.message = "your custom message"
history_instance.save()
You could generate a pretty generic signal that works for all your models tracked with a 'history' field.
Note: I renamed "nacimiento" as "birthdate" to keep consistency in naming all the fields in english.
I am trying to create the following models. There is a ManyToMany relation from Entry to AUTH_USER_MODEL via the EntryLike intermediate model.
class BaseType(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
creation_time = models.DateTimeField(auto_now_add=True)
last_update_time = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Title(BaseType):
text = models.CharField(max_length=100)
description = models.TextField()
class EntryLike(BaseType):
entry = models.ForeignKey(Entry)
user = models.ForeignKey(settings.AUTH_USER_MODEL)
class Entry(BaseType):
title = models.ForeignKey(Title, on_delete=models.PROTECT)
text = models.TextField()
user = models.ForeignKey(settings.AUTH_USER_MODEL)
liked_by_users = models.ManyToManyField(settings.AUTH_USER_MODEL, through='EntryLike', through_fields=('entry', 'user'))
Running migrations on the above model scheme throws the error: AttributeError:'str' object has no attribute 'meta'.
Any help in resolving this error would be highly appreciated. Am new to Django & Python, but not to Web Development.
The issue is that settings.AUTH_USER_MODEL is almost certainly not a model instance. It's probably a string that constrains the choices another model can make - settings would be a strange place to leave a model definition.
To do a MTM between the user model and your field above you need need to do:
from django.contrib.auth.models import User
class Entry(BaseType):
title = models.ForeignKey(Title, on_delete=models.PROTECT)
text = models.TextField()
user = models.ForeignKey(User)
def __str__(self):
return self.title
I've added the str function so that it gives a more sensible return when you're manipulating it in admin/shell.
I'd also question whether you need the second set of fields (removed here), as you can use select related between the Entry and EntryLike join table, without any duplication of the fields - you can probably go that way, it's just a bit unnecessary.
Lastly, I'd note that the way I'm using it above just uses the default User object that comes with Django - you may wish to customise it. or extend the base class as you've done here with your own models' base class.
(All of this is predicated on AUTH_USER_MODEL not being a model instance - if it is, can you post the model definition from settings.py? )
I'm trying to create a unique constraint on my TranslationRequest model listed below. TranslationRequest has a foreign key relationship with a MachineTranslator model, which exists in another Django application. When I try to run syncdb, I get the error: Error: One or more models did not validate:
wt_articles.translationrequest: "unique_together" refers to translator, a field that doesn't exist. Check your syntax.
When I remove translator from the unique_constraint specification, syncdb runs correctly. Note: I'm using Sqlite3 as my back-end database.
Here are the definitions of TranslationRequest and SourceArticle.
from wt_translation.models import MachineTranslator
class TranslationRequest(models.Model):
article = models.ForeignKey(SourceArticle)
target_language = models.ForeignKey(Language, db_index=True)
date = models.DateTimeField(_('Request Date'))
translator = models.ForeignKey(MachineTranslator),
status = models.CharField(_('Request Status'),
max_length=32,
choices=TRANSLATION_STATUSES)
class Meta:
unique_together = ("article", "target_language", "translator")
class SourceArticle(models.Model):
title = models.CharField(_('Title'), max_length=255)
language = models.ForeignKey(Language, db_index=True)
timestamp = models.DateTimeField(_('Import Date'), default=datetime.now())
doc_id = models.CharField(_('Document ID'), max_length=512)
source_text = models.TextField(_('Source Text'))
sentences_processed = models.BooleanField(_('Sentences Processed'))
Here is the definition of MachineTranslator, in a different (but referenced Django application).
class MachineTranslator(models.Model):
shortname = models.CharField(_('Name'), max_length=50)
supported_languages = models.ManyToManyField(LanguagePair)
description = models.TextField(_('Description'))
type = models.CharField(_('Type'), max_length=32, choices=TRANSLATOR_TYPES, default='Serverland'),
timestamp = models.DateTimeField(_('Refresh Date'), default=datetime.now())
is_alive = models.BooleanField()
Not all of the dependencies have been included in this code sample. Thanks for your help!
i dont' know if it is a typo but i see s "," comma at the end of the line where you declare your translator = models.ForeignKey(MachineTranslator)
This is why maybe the attribute is ot seens