I'm working on a Django webapp.
I'm trying to create a user from signup form.
I made sure that there is no user in DB with that username and entered data in signup form and hit enter.
There is a default language field that is populated with txt in User user model.
I'm using the following function to populate that field.
def get_default_language():
lang=Language.objects.get_or_create(
name='Plain text',
lang_code='text',
slug='text',
mime='text/plain',
file_extension='.txt',
)
return lang[0].id
But it's giving me the below error
IntegrityError at /signup/
UNIQUE constraint failed: djangobin_language.lang_code
Here is the code for Language model
class Language(models.Model):
name=models.CharField(max_length=100)
lang_code=models.CharField(max_length=100, unique=True, verbose_name="Language Code")
Isn't it supposed to get or create the row in Language table? Why am I getting this error?
Your model is not complete. You.sre.passing different values for the get_or_create and because it can't find the exact object you are searching for than it tries to create one but the language code it's already used and you get the unique issue.
I suggest you to use a choices option on your language code field and pass a tuple with the ISO state definitions.
I also suggest you to retrieve based only the language code field and then decide or to update.the object based the other field passed or create a new language object. You must implement your own method to do that
Related
So long story short, I have a Car model and a CarVersion model and I want the user to have the ability to choose from the availble car versions saved in the database, through a html select field.
I cannot understand how to dynamically generate the choices field from the CarVersion model. I have the function, but I cannot call it inside the Car model.
Here is the code I have so far:
class Car(models.Model):
choices = get_choices()
name = models.CharField(max_length=50, unique=True)
version = models.ForeignKey(CarVersion, choices=get_choices(), on_delete=models.RESTRICT)
#staticmethod
def get_choices():
options = CarVersion.objects.all().values_list("pk", "name")
try:
if not options:
return [(0, "No versions in database. Call your administrator.")]
except ProgrammingError:
return [(0, "No versions in database. Call your administrator.")]
return [(1, "Test")]
I want to call the function get_choices in
version = models.ForeignKey(CarVersion, choices=get_choices(), on_delete=models.RESTRICT)
but I don't know how to do that while the function is declared to the model. If I define it outside of the model, it works, but there must surely be a better way that im missing, rather than cluttering my models.py file with a bunch of model specific functions.
P.S.get_choices is not finished but as soon as I can call it, I will deal with it.
I would advise against doing it this way for several reasons. The choices parameter on the model field is for validating data you could potentially add to the database.
Besides that, the way yo write it, the function that fetches the CarVersion objects is called when the module is loaded. This is a bad idea. You may want to import the module in some place at a time when you don't even have a database connection yet.
The proper way to to this, since your intent is to generate options in an HTML form for the user, would be to rely on the foreign key capabilities of the Django Forms. The ModelChoiceField should already do what you need.
PS: In fact the ModelChoiceField is automatically instantiated, when you create a ModelForm from a Model that has a ForeignKey field. See the list of field conversion on the ModelForm page.
I want to thank Daniil for his contribution, for without it, I would have never been able to ask the correct question for my problem, which is:
How to dynamically generate a choices field.
The answer to that question can be found at:
How to create a dynamic Django choice field
First of all I have tried to research my problem but have not been able to find what I need. My problem might be related to the design of my project (any help would be appreciated).
The problem I am facing is as follows:
I have a few models
I have a model that would be used specifically to create a ModelForm
In this model I have ForeignKey field that is represented by default as a select/option input widget in the ModelForm (for each the value attribute is the ForeignKey and text between the tags is the __str__() of the model the ForeignKey points to. The user sees the __str__() and value attribute of the option tag is submitted which is great).
So far so good but I want to replace the widget with an input text field so I can implement it as a search field.
Now when the user submits the form the string entered in the text input field is submitted and of course django doesn't like that since it expects a foreign key
I already can think of a few solutions to the problem and I am sure I can make it work but each of them feels like I would be violating some best practices. So my question is what should I do?
Do I exclude this particular field from the ModelForm and implement it as an input text field then after form submission make a query with it's value and then store the ForeignKey to the DB
Do I manipulate the data with JavaScript upon submission so that Django receives correct information
Can I clean this fields data with Django and transform it from string to FK?
Am I going the wrong way with this or there is a Django feature for this type of situation?
If anyone has the same problem here is the solution (to my problem at least):
I tried to use the clean_<fieldname> method to change the user entered string to database id. The method wasn't executing because the validation process was stopping earlier because of the difference between the form field and the widget. I redefined the form field to CharField so that step of the validation was working and then the clean_<fieldname> method executes without a problem.
I am creating model class Car and I want to have in it two references to one foreign key.
class Car(models.Model):
owner = models.ForeignKey(User)
#and here I want to have owner email (which is already set in class User)
email = owner.email
But I don't know how to make reference to field of ForeignKey already used.
I get this error:
AttributeError: type object 'User' has no attribute 'email'
Is there any way to do it?
There are two things here... the first is to find out why you want to do this. Because maybe you shouldn't.
If you just want to access the owner's email address from a Car instance you don't need to add it as a field on the Car model, you can do:
my_car = Car.objects.get(owner=me)
my_email = my_car.owner.email
This does two seperate db queries, the first to get the Car and the second to get the owning User when you access the ForeignKey.
If you want to avoid this you can use select_related:
my_car = Car.objects.select_related().get(owner=me)
my_email = my_car.owner.email
Now it's only one query, Django knows to do a join in the underlying SQL.
But, assuming you know all this and you still really want to add the owner's email to the Car model. This is called 'denormalisation' and there can be valid performance reasons for doing it.
One problem that arises is how to keep the email address in sync between the User and Car models. If you are deliberately pursuing denormalisation in your Django app I highly recommend you consider using django-denorm. It installs triggers in the SQL db and provides a nice interface for specifying denormalised fields on your model.
You should really follow django's tutorial...
You can access the user email with car_instance.owner.email.
There is no need to add existing fields to another module. You should in principle avoid repeating data. Since the email and all relevant user info exist in the user model, then the foreign key is enough to access this data in relevance to a specific car record:
car = Car.objects.first()
email = car.owner.email
You can do the same with any field of the user model.
I realized that when I have a simple model:
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
views = models.IntegerField(default=0)
likes = models.IntegerField(default=0)
the modifier unique=True has the effect that when I add a category to the database (via an HTML form) which has a name of an instance already present in the database, the application will not crash.
Instead, I get access to form.errors which I can print to the page or to the terminal.
If I omit unique=True and I try to add a category to the database with a name that already exists, I get an IntegrityError and my application crashes.
So it seems to me that defining unique=True is pretty important for the behaviour of the application. I guess then there must be other model attributes which are equally importa
In the django documentation, where can I read about this and if there are other such attributes?
First of all, you created the model using the unique constraint, so the database already has the unique constraint.Something like (for MySQL):
CONSTRAINT myapp_category UNIQUE (name)
Now, you are probably using a ModelForm, which picks this attribute unique=True, and applies that validation. So, you can catch the errors via form.errors and handle it gracefully.
When you remove the attribute, the database still has the constraint, but the ModelForm does not perform that validation for you, hence the IntegrityError
So, to answer your question - unique=True does help prevent raising of an exception when you use it in the context of a ModelForm, or you would have to handle it yourself to make it fail gracefully.
To remove the unique constraint from the database, you would have to use a migration tool like south
My guess is that you have a database model which has a UNIQUE constraint on the name column. If you try to insert two rows with the same name, then the database (via the database driver) will throw an IntegrityError. This happens completely independent of django.
django then has a model how to build forms. If you omit the unique=True, django assumes that the column in the database isn't unique and doesn't add the necessary checks in the form validation step.
So you basically have a config mismatch between your form and your database.
Solutions:
Make sure the constraints for forms and database columns are always the same
Write your own, custom validation rules (see the django documentation).
Alternatively: Write code that gets unique constraints from the database and then, when you create a form, check that the necessary attributes are set to avoid this error.
I followed the method of extending the User class for implementing custom users in my application.
As mentioned in the link, custom authentication backend needs to be written in order to return the appropriate custom user class rather than User.
However I have more than one custom users class, namely Student, Teacher,Parent.
Is there any better way than checking Student->Teacher->Parent tables to return the correct custom user?
The only solution I could think of is to actually change the User model that django uses and add a content_type field that would tell you what type of user the actual user object is. Then you could directly query on that one. You'd still need 2 queries every time to fetch the correct user object.
Alternatively you could have a model that inherits from User that encompasses all of the functionality required by your three classes, call it SuperUser for example, with a special field identifying if it is a Student, Teacher or a Parent.
Then fetch the SuperUser object for a user, thus containing all of the required data. By using the special field identifying which user type they are, you could have a proxy model that you have for each type of user (ProxyStudent, ProxyTeacher, etc) that would make it behave as it should.
This would mean you only ever have 2 database hits regardless, but you get to store the data as specified as long as you use the proxy model to access them.
class SuperUser(User):
type = models.IntegerField(choices=[(0, 'Student'), (1, 'Teacher'), (2, 'Parent')]
# insert all the data for all 3 seperate classes here
class ProxyStudent(SuperUser):
class Meta:
proxy = True
def special_student_method(self):
pass
fetch request.user
and make request.user an instance of SuperUser
student = ProxyStudent()
student.__dict__ = request.user.__dict__