So i have this model:
class Token(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=False)
code = models.IntegerField(default=code)
date_created = models.DateTimeField(auto_now_add=True)
expiration_date = models.DateTimeField(null=False, blank=True)
as you can see I have an expiration_date field. The reason why I set it to (null=False, blank=True) is because I want it to fill itself based of the date_created field, and I'm trying to do that from the model manager create method
I have little to no experience in model manager outside of custom user model manager.
Here's my first failed attempt:
class TokenManager(models.Manager):
def create(self, user, code, date_created):
exp = date_created + datetime.timedelta(minutes=10)
token = self.model(user=user, code=code, date_created=date_created, expiration_date=exp)
token.save()
return token
basically my goal here is to get the value of date_created field, add the value by 10 minutes and set it as the expiration_date. can anyone help me with this?
There is no need to use a ModelManger here. You can just set the expiration_date based on the field date_created by overwriting the save method.
Edit:
It is not possible to use self.date_created datetime within the save method. However it is possible to use django.utils.timezone.now()which is also used by auto_now_add .
from django.utils import timezone
class Token(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=False)
code = models.IntegerField(default=code)
date_created = models.DateTimeField(auto_now_add=True)
expiration_date = models.DateTimeField(null=False, blank=True)
def save(self, *args, **kwargs):
# Set the expiration_date based on the value of auto_now_add
self.expiration_date = timezone.now() + datetime.timedelta(minutes=10)
super(Token, self).save(*args, **kwargs)
Related
Im new to django and im trying to figure out how to set the value in a model = to a value in another model
from django.db import models
from django.contrib.auth.models import User
class Company(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
name = models.CharField(max_length=100, null=True, blank=True) # This is the value I want
_id = models.AutoField(primary_key=True, editable=False)
def __str__(self):
return self.name
class Product(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE, null=True)
companyName = # I want the name here
_id = models.AutoField(primary_key=True, editable=False)
def __str__(self):
return self.name
I've tried these but they dont work
companyName = Company.name
companyName = models.CharField(Company.name, max_length=100, null=True, blank=True)
Company.name will not work because Company is a class, a template for making many Company objects, each with it's own name, so which Company object, or instance, do you want?
You need to get the particular Company first, and then you can set the companyName of the Product, or, you can set it when you save the Product instance, assuming you have a Company instance in mind, since you set null=True, so obviously if company is False, then there is no companyName.
Assuming you have a Company instance already when you save the Product model you can do:
class Product(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE, null=True)
companyName = # I want the name here
_id = models.AutoField(primary_key=True, editable=False)
def save(self, *args, **kwargs):
if self.company:
self.companyName = self.company.name
super(Product, self).save(*args, **kwargs)
def __str__(self):
return self.name
But, the next question is why do you want to even have a field called companyName when you have access to the name field of the Company instance anyway. Try to get it by:
# Get the Product instance you want
product = Product.objects.get(...)
# Then you can get the associated `Company` name like this:
print(product.company.name)
Suggestion
Lately I've been seeing many questions with something like:
_id = models.AutoField(primary_key=True, editable=False)
Not sure why, since Django does that automatically.
I have user model that has a one to one relation with two other models.
these are my models:
class User(AbstractUser):
id = models.AutoField(primary_key=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
isPreRegistered = models.BooleanField(default=False)
username = models.CharField(unique=True, max_length=13)
first_name = models.CharField(max_length=32, null=True, default=None)
last_name = models.CharField(max_length=64, null=True, default=None)
progress_level = models.CharField(max_length=25, null=True, choices=USER_PROGRESS_LEVELS)
class ScientificInfo(models.Model):
id = models.AutoField(primary_key=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
final_assessment = models.TextField(null=True, blank=True)
is_interviewed = models.BooleanField(default=False)
class PsychologicInfo(models.Model):
id = models.AutoField(primary_key=True)
user = models.OneToOneField(User, on_delete=models.CASCADE)
final_assessment = models.TextField(null=True, blank=True)
is_interviewed = models.BooleanField(default=False)
I want to update the user's progress_level if PsychologicInfo.is_interviewed and ScientificInfo.is_interviewed are both True. So I thought I should override the save method and added this to the user model:
def save(self, *args, **kwargs):
if self.scientificinfo.is_interviewed == True and self.psychologicinfo.is_interviewed == True:
self.progress_level = USER_PROGRESS_LEVELS[1][0]
return super(User, self).save(*args, **kwargs)
But I have to save the User object one more time to see some results. how can I update my progress level field when PsychologicInfo and ScientificInfo get saved?
I think you can use the Django signals a post_save can be what you need.
U can make a check if the instance PsychologicInfo or ScientificInfo
are updated or created then update the progress
voila an example of what you may want:
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import PsychologicInfo, ScientificInfo
# import your choices USER_PROGRESS_LEVELS
#receiver(post_save, sender=PsychologicInfo)
def pre_save_receiver(sender, instance, *args, **kwargs):
if instance:
if instance.psychologicinfo.is_interviewed:
instance.progress_level = USER_PROGRESS_LEVELS[1][0]
# Do other operation ...
You duplicate the this code by changing the sender and change the logique of your condition. it should work just fine
I am trying to implement a data warehouse. So the django system will query an api at regular intervals to update the database. I am using client ids as the primary key which might be the problem but when I do save I obviously want it to create or update.
I get this error whatever I do!
django.db.utils.IntegrityError: null value in column "created" violates not-null constraint
So originally I just had my model like this:
class PersonalTaxClient(models.Model):
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
invoice_client = models.ForeignKey(InvoiceClient, blank=True, null=True, on_delete=models.PROTECT)
client_name = models.CharField(max_length=100)
email = models.CharField(max_length=100)
Then I tried:
class PersonalTaxClient(models.Model):
created = models.DateTimeField(editable=False)
updated = models.DateTimeField()
client_code = models.CharField(max_length=20, primary_key=True)
invoice_client = models.ForeignKey(InvoiceClient, blank=True, null=True, on_delete=models.PROTECT)
client_name = models.CharField(max_length=100)
email = models.CharField(max_length=100)
# history = HistoricalRecords()
def save(self, *args, **kwargs):
''' On save, update timestamps '''
print(timezone.now())
if not self.client_code:
self.created = timezone.now()
self.modified = timezone.now()
return super(PersonalTaxClient, self).save(*args, **kwargs)
and try to update like this:
>>> from sbsite.models import PersonalTaxClient
>>> p = PersonalTaxClient(client_code="HHH001", client_name="Bob")
>>> p.save()
I get the same error. I've read about 20 other SO pages but am none the wiser..............!
Hi I am trying to add "fields" to my django projects that would be calculated based on query..
Basically I have 2 models one is a user which is an extension of Abstract user
class CustomUser(AbstractUser):
pass
and my main model is Project
class Project(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(CustomUser, on_delete=models.PROTECT, editable=False)
name = models.CharField(max_length=20, editable=False)
total = models.DecimalField(max_digits=6, decimal_places=2, editable=False)
created = models.DateTimeField(auto_now_add=True, editable=False, null=False, blank=False)
this_month = datetime.datetime.now().month
allprojectsthismonth = Project.objects.filter(created__month=this_month)
def __str__(self):
return self.name
I create Project objects via a web form using this view:
def homepage(request):
if request.method == "POST":
project = Project()
name = request.POST.get('name')
total = request.POST.get('total')
created = datetime.datetime.now()
user = request.user
project.user = user
project.name = name
project.total = total
project.created = created
project.save()
#return HttpResponse(reverse("homepage.views.homepage"))
return render(request, 'homepage.html')
else:
return render(request, 'homepage.html')
What I need now is to have a queryset that gets me the combination of the total of a given user Project object so that I can make calculations on it, how would I go about doing that?
ideally I would get the logged in user and I could add to my view the sum of all Project.object.total with user = currently logged in.
Thanks
EDIT: Would this work?
class Project(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(CustomUser, on_delete=models.PROTECT, editable=False)
name = models.CharField(max_length=20, editable=False)
total = models.DecimalField(max_digits=6, decimal_places=2, editable=False)
created = models.DateTimeField(auto_now_add=True, editable=False, null=False, blank=False)
this_month = datetime.datetime.now().month
projectsthismonth = self.objects.filter(created__month=this_month)
def monthlyTotal(self,request):
projectsthismonth.objects.filter(
user=request.user
).aggregate(
sum_total=Sum('total')
)['sum_total']
I seem to be missing something however.
You can obtain the queryset of the Projects where the user is the logged in user with:
Project.objects.filter(user=request.user)
If you want to make simple aggregates (like sum, count, etc.), you better use .aggregate(…) [Django-doc] since then the calculations are done at the database level. For example:
from django.db.models import Sum
Project.objects.filter(
user=request.user
).aggregate(
sum_total=Sum('total')
)['sum_total']
will retrieve the sum of the totals of the Projects with user=request.user, this will be None if there are no projects related to the user at all.
from django.utils.timezone import now
class Project(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(CustomUser, on_delete=models.PROTECT, editable=False)
name = models.CharField(max_length=20, editable=False)
total = models.DecimalField(max_digits=6, decimal_places=2, editable=False)
created = models.DateTimeField(auto_now_add=True)
def monthlyTotal(self,user):
this_month = now().month
return Project.objects.filter(
created__month=this_month,
user=user
).aggregate(
sum_total=Sum('total')
)['sum_total']
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
This is how my model looks like. When ever user orders. The order id provided by django is simple. Its like 1,2,3 ..... 100.
class UserOrder(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='orders',
on_delete=models.CASCADE)
cart = models.ForeignKey(Cart, related_name="orders", on_delete=models.CASCADE, null=True,
blank=True)
date = models.DateTimeField(default=datetime.now)
total_price = models.IntegerField(null=True, blank=True)
note = models.TextField(null=True, blank=True)
cancel_reason = models.TextField(null=True, blank=True)
cancelled = models.BooleanField(default=False)
confirmed = models.BooleanField(default=False)
def __str__(self):
return self.user.username
Your question is not well defined but I think I understand your problem, you need a id (lookup field) that is not simple.
you can use uuid, and use this uuid for all the lookup in the viewsets, instead of the sequentially created id by django.
something like this lookup_field = 'uuid' in views.
import uuid
class UserOrder(models.Model):
uuid = models.UUIDField(default=uuid.uuid4, unique=True, db_index=True, editable=False)
read more about uuids here https://docs.python.org/3/library/uuid.html#uuid.uuid4
try using the django-random-id-model
run pip install django-random-id-model
in your django models.py file import RandomIDModel from django-random-id-model
then add RandomIdModel to your model class, in case this is:
class UserOrder(RandomIdModel):
#remaining codes here