Django - Remove Unique Constraint from a field - django

I have a model like
class LoginAttempts(models.Model):
user = models.OneToOneField(User, unique=False)
counter = models.IntegerField(null=True)
login_timestamp = models.DateTimeField(auto_now=True)
The table created in db is like
However If I create another entry with user_id = 362 it fails with IntegrityError: duplicate key value violates unique constraint. Id is already my primary key, I want to have same user having different counters instead of creating a new table referencing them since this is simple table.
How to achieve the same or what what could be the best way. I want to restrict user to some specified number of failed logins.

If you want a relationship that permits more than one LoginAttempt for a User, you should not use OneToOneField. by definition, that implies only one item on each side. Instead, use ForeignKey.

The very nature of a OneToOneField is that it's a ForeignKey with a unique constraint.
However, if you don't want separate entries, then update the counter and login_timestamp fields:
from django.utils import timezone
def update_attempts_for_user(user):
attempts, created = LoginAttempts.objects.get_or_create(user=user, defaults={'counter': 1, 'login_timestamp': timezone.now())
if not created:
attempts.counter += 1
attempts.login_timestamp = timezone.now()
attempts.save(update_fields=['counter', 'login_timestamp'])

Related

How to save a Foreign Key in Django without instance, but a hard coded value

Suppose I have these 2 models:
class Shipment(models.Model):
id = models.BigIntegerField(primary_key=True)
order_id = models.ForeignKey('orders.Order', null=True, blank=True, on_delete=models.SET_NULL)
class Order(models.Model):
id = models.BigIntegerField(primary_key=True)
ean = models.BigIntegerField(null=True, blank=True)
The orders are already populated in the database, now I just want to link the shipments to the related order. But I have a list of hardcoded JSON to populate my shipment model.
{
"shipmentId": 541757635,
"orderId": 23598235,
}
So the orderId in that JSON represents the primary key of a Order model that is already present in the database. How can I loop over this to connect the shipment model with the correct order model based on the order_id?
Maybe a loop like this:
for shipment in shipments:
shipment = Shipment.objects.create(id=shipment.shipmentId, order_id=shipment.orderId
But is this possible because there is no instance, just a hard coded value in the JSON?
UPDATE:
So when I try to use this loop I get this error:
self.field.remote_field.model._meta.object_name,
ValueError: Cannot assign "2647598550": "Shipment.order_id" must be a "Order" instance.
Your example loop should do it. You can specify the ID to be anything you want, as long as you do it before calling .save(). Building the instance with .create(id=foo) should do exactly that.
To set a foreign key field, you can first get the related instance using the id with Order.objects.get(id=order_id).
Example code:
for shipment in shipments:
order = Order.objects.get(id=shipment.orderId)
shipment = Shipment.objects.create(id=shipment.shipmentId,
order_id=order)
Related: Django error. Cannot assign must be an instance
Source: https://docs.djangoproject.com/en/2.2/ref/models/instances/#explicitly-specifying-auto-primary-key-values

Django view retrieve model id of instance just created

I have a simple scenario trying to retrieve the id/pk of a model instance created in a view. The model instance is creating fine however the id/pk is returning "None". I thought I was following the code as laid out in the latest documentation but I must be doing something wrong.
Models.py
class Userdownloads(models.Model):
id = models.IntegerField(primary_key=True)
created_by = models.ForeignKey(User,on_delete=models.DO_NOTHING, related_name='Download_created_by',null=True,blank=True)
created_date = models.DateTimeField(auto_now_add=True)
Views.py
d = Userdownloads(created_by=request.user)
d.save()
print(d.id)
Ive tried both d.id and d.pk
Can anybody help my see where I am going wrong? Any help is much appreciated!
On save call of the given example should throw an error like this:
null value in column "id" violates not-null constraint
So, here the id field should be AutoField. For example:
id = models.AutoField(primary_key=True)
From the documentation,
AutoField
An IntegerField that automatically increments according to available IDs. You usually won’t need to use this directly; a primary
key field will automatically be added to your model if you don’t
specify otherwise
You don't have to specify id on django models because it will automatically create for you.
class Userdownloads(models.Model):
created_by = models.ForeignKey(User,on_delete=models.DO_NOTHING, related_name='Download_created_by',null=True,blank=True)
created_date = models.DateTimeField(auto_now_add=True)
Here is the link to the models
If it give you None then it has not been saved to the database yet.

Model with autoincremental non PK key

I'm writing a model where I use an auto incremental key, which is based on two foreign keys and is not the pk.
class Message(models.Model):
message_id = models.IntegerField()
user_1 = models.ForeignKey(User)
user_2 = models.ForeignKey(User)
class Meta:
unique_together = ("message_id", "user_1", "user_2")
As far as I know, an AutoField can't be used for this case.
What is the best way to achieve this. (It might be the case, that two new messages are created at the same time).
Django doesn't support composite primary keys, yet, so best way is pretty much the way you're doing it now.
Keep the automatic id column that Django generates and then add a unique index for the columns that actually are the primary key, the unique index will then take care of ensuring that there's no duplicates.

django - how do I join the results of multiple models having foreign key the same user?

I have multiple models that point to the same user like this:
class Model1(moldels.Model):
user = models.ForeignKey(User)
title = models.CharField()
...
class Model2(moldels.Model):
user = models.ForeignKey(User)
...
class Model3(moldels.Model):
user = models.ForeignKey(User)
...
What to be able to do a search/filter on title field on Model1 and join the results from the other models that have the same user. Only Moldel1 will return multiple results for the same user. Model2 and Model3 will always return one result for every user (like one avatar and one profile). - Thank you!
It depends on what you mean by "join". You can access one from any other though user and the related_name of the model (by default: <lowercase class name>_set), e.g.:
model1_instance.user.model2_set.all()
Or you can use the user instance to access each directly:
user.model1_set.all()
user.model2_set.all()
user.model3_set.all()
You can query those models through the user as well, with query traversals:
User.objects.filter(model1__title='some title')
Finally, for the models that have only one instance, such as one profile per user, you should really be using OneToOneField instead of ForeignKey. If you do that, then you can use select_related on any reverse relation that is a OneToOneField (true SQL JOIN), e.g.:
User.objects.filter(model1__title='some title').select_related('model2', 'model3')
However, select_related will not work on reverse foreign key relationship or many-to-many relationships. For that, you'll have to wait until Django 1.4 drops with prefetch_related.
If you want get a queryset, this is impossible. You cannot get a queryset of various models.
But I think that you want something like this:
objs1 = Model.objects.filter(title__icontains='YOUR FILTER')
users = objs1.values('user').distinct()
objs2 = Model2.objects.filter(user__in=users)
objs3 = Model3.objects.filter(user__in=users)
objs = list(objs1)
objs.extend(list(objs2))
objs.extend(list(objs3))
return objs

Designing without duplicate foreignkey references in Django

I want to create an expense tracking application, where each user can enter expenses and classify them into his own categories. Here is the model definition that I use:
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
user = models.ForeignKey(User, related_name="my_categories")
name = models.CharField(max_length=50)
class Expense(models.Model):
date = models.DateField()
amount = models.IntegerField()
description = models.TextField()
category = models.ForeignKey(Category)
user = models.ForeignKey(User)
Each category will have to be associated with a user so that we can display each user his own categories to choose while entering the expense. For similar reasons, each expense record should be associated with a user. But in definition of Expense, we are having 2 references to the User models, one directly through 'user' field and another through the 'category' field which has a user reference.
I believe that multiple references like this is a bad thing. Is there a better way to model this? I understand that we can find out the user from the category reference, but it seems a roundabout way of doing it.
Although your db is not 100% normalized, in your case, I do not believe the second reference is redundant. Both 'an expense' and 'a category' are well defined entities, which belong to a user. If you will later want to change your foreign key to allow a null category or to a ManyToManyField, you will notice immediatly that both user fields are required. Lookups by user are also much easier for the db and developer when the column is there.