getting error- i saved one form from html into my database
while when i tried saving the next it gave me this error-
IntegrityError at customer
(1062, "Duplicate entry 'ad138e46-edc0-11va-b065-a41g7252ecb4'' for key 'customer.PRIMARY'")
kindly explain my uuid in models.py is -
class customer(models.Model):
customerid = models.CharField(default=str(uuid.uuid4()), max_length=500, primary_key=True)
customername=models.CharField(max_length=100)
kindly help
Updated
Form.py
class createcustomerform(ModelForm):
class Meta:
model=customer
fields=[
'customername']
Updated Models.py
import uuid
from uuid import UUID
from django.contrib.auth.models import User
from django.dispatch.dispatcher import receiver
from django.utils.translation import ugettext_lazy as _
from django.db.models.signals import pre_save
class customer(UUIDMixin,models.Model):
customername=models.CharField(max_length=100)
def __str__(self):
return self.customername
class UUIDMixin(models.Model):
uuid = models.UUIDField(blank=True,db_index=True,default=None,help_text=_('Unique identifier'),max_length=255,null=True,unique=True,verbose_name=_('UUID'))
class Meta:
abstract = True
#classmethod
def check_uuid_exists(cls, _uuid):
#Determine whether UUID exists """
manager = getattr(cls, '_default_manager')
return manager.filter(uuid=_uuid).exists()
#classmethod
def get_available_uuid(cls):
#Return an Available UUID """
row_uuid = uuid.uuid4()
while cls.check_uuid_exists(uuid=row_uuid):
row_uuid = uuid.uuid4()
return row_uuid
#receiver(pre_save)
def uuid_mixin_pre_save(sender, instance, **kwargs):
if issubclass(sender, UUIDMixin):
if not instance.uuid:
manager = getattr(instance.__class__, '_default_manager')
use_uuid = uuid.uuid4()
while manager.filter(uuid=use_uuid):
use_uuid = uuid.uuid4()
instance.uuid = use_uuid
#Automatically populate the uuid field of UUIDMixin models if not already populated.
You should use a proper UUIDField and avoid setting a default value.
Make sure the value is set when the object is created, and also ensure that the value is unique - obviously the chance of duplication in a UUID is incredibly small which is the whole point.
You could create yourself a model mixin which will add a uuid to your model(s) and ensure that the value is set when the object is saved;
class UUIDMixin(models.Model):
"""
Mixin for models contain a unique UUID, gets auto-populated on save
"""
uuid = models.UUIDField(
blank=True,
db_index=True,
# default=uuid.uuid4,
# NB: default is set to None in migration to avoid duplications
default=None,
help_text=_('Unique identifier'),
max_length=255,
null=True,
unique=True,
verbose_name=_('UUID'),
)
class Meta:
"""Metadata for the UUIDMixin class"""
abstract = True
#classmethod
def check_uuid_exists(cls, _uuid):
""" Determine whether UUID exists """
manager = getattr(cls, '_default_manager')
return manager.filter(uuid=_uuid).exists()
#classmethod
def get_available_uuid(cls):
""" Return an Available UUID """
row_uuid = uuid.uuid4()
while cls.check_uuid_exists(uuid=row_uuid):
row_uuid = uuid.uuid4()
return row_uuid
#receiver(pre_save)
def uuid_mixin_pre_save(sender, instance, **kwargs):
"""
Automatically populate the uuid field of UUIDMixin models if not already
populated.
"""
if issubclass(sender, UUIDMixin):
if not instance.uuid:
manager = getattr(instance.__class__, '_default_manager')
use_uuid = uuid.uuid4()
while manager.filter(uuid=use_uuid):
use_uuid = uuid.uuid4()
instance.uuid = use_uuid
Based on your comment, let me explain more.
The above is an abstract model, meaning it doesn't create a table itself, it can just be used by other (concrete) models so that they can use what it defines.
It's a benefit of classes & inheritance. Allowing you to not duplicate code on things that will be useful on many models.
No, in the meta you'll see abstract = True. So you define your models like MyModel(UUIDMixin, models.Model) and it gets a uuid field from this abstract model along with whatever you define.
You would use it by doing something like this;
class Customer(UUIDMixin, models.Model):
name = models.CharField(max_length=100)
If you really want to use the UUID as a primary key, maybe setup two mixins, a PrimaryUUIDMixin and the UUIDMixin, because on the whole a smaller value on the primary key may be more efficient.
You also mentioned Undefined variable: _
Typically in django you'd see an import at the top of the file like this;
from django.utils.translation import ugettext_lazy as _
This is then used to wrap strings so that they can be translated, for example, _("Hello")
Even if you don't translate your project, it's common to just include this anyway. You can read up on that here; https://docs.djangoproject.com/en/3.1/topics/i18n/translation/#standard-translation
Related
Hey I am using the First Parameter as a model but still it keeps on giving the error:
First parameter to ForeignKey must be either a model, a model n
ame, or the string 'self'
for my code.
It works totally well if I use 'self' as first parameter for foreign key. but thats not what I want. Also i am unable even to makemigrations after the following code.
models.py
from django.db import models
import datetime
from django.utils import timezone
class commentt(models.Manager):
comment_id=models.IntegerField(primary_key=True)
name=models.CharField(max_length=100, default="No Comment Added")
comment_created=models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
# Create your models here.
class task_check_manager(models.Manager):
def create_task(self, title,c1,c2,c3,list,score_occurence,score_occurence_csm,To):
Task_check = self.create(title=title,c1=c1,c2=c2,c3=c3,list=list,score_occurence=score_occurence,score_occurence_csm=score_occurence_csm,To=To)
# do something with the book
return Task_check
class task_check(models.Model):
LIST = (
('DAILY', 'DAILY'),
('WEEKLY','WEEKLY'),
('FORTNIGHT','FORTNIGHT'),
('MONTHLY','MONTHLY')
)
STATUS=(
('YES','YES'),
('NO','NO'),
('NEUTRAL','NEUTRAL')
)
title=models.CharField(max_length=50)
c1=models.CharField(max_length=20,default='C1')
c2=models.CharField(max_length=20,default='C2')
c3=models.CharField(max_length=20,default='C3')
From=models.DateTimeField(default=timezone.now())
To=models.DateTimeField(default=timezone.now())
#created_task=models.DateTimeField(auto_now_add=True)
status=models.CharField(max_length=15,default="NEUTRAL",choices=STATUS)
list=models.CharField(max_length=15, default='DAILY',choices=LIST )
score_occurence_csm=models.IntegerField(default=0)
score_occurence=models.IntegerField(default=0)
comments=models.ForeignKey(commentt, on_delete=models.SET_NULL, null=True)
vendor=models.TextField(max_length=200,default="NONE", editable=False)
objects = task_check_manager()
def __str__(self):
return self.title
You Commentt model is indeed not a model, it is a manager. You should make it a subclass of Model:
class Commentt(models.Model): # <- Model, not Manager
comment_id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100, default="No Comment Added")
comment_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
Note: According to the PEP-8 Style Guide, the classes should be written in PerlCase, and the fields in snake_case.
I know this is not a solution to your problem but I was shown the same error for missing the (models.Manager) on a model class. I am sharing this because it might help someone else.
When implementing GraphQL update mutations with many (here just a and b) optional InputObjectType fields it generates a lot of boilerplate to check if the InputObjectTypes fields have been passed. Is there some idiom which is considered best practice w.r.t. this topic?
# <app>/models.py
from django.db import models
class Something(models.Model):
a = models.CharField(default='')
b = models.CharField(default='')
# <app>/schema.py
import graphene
from graphene_django import DjangoObjectType
from .models import Something
class SomethingType(DjangoObjectType):
class Meta:
model = Something
class SomethingInput(graphene.InputObjectType):
# all fields are optional
a = graphene.String()
b = graphene.String()
class SomethingUpdateMutation(graphene.Mutation):
class Arguments:
id = graphene.ID(required=True)
something_data = SomethingInput(required=True)
something = graphene.Field(SomethingType)
def mutate(self, info, id, something_data):
something_db = Something.objects.get(pk=id)
# checking if fields have been passed or not and
# only change corresponding db value if value has been passed
if something_data.a is not None:
something_db.a = something_data.a
if something_data.b is not None:
something_db.b = something_data.b
something_db.save()
return SomethingUpdateMutation(something=something)
class Mutation(object):
# project schema inherits from this class
something_update_mutation = SomethingUpdateMutation.Field()
You can do this:
def mutate(self, info, **kwargs):
user = info.context.user
for k, v in kwargs.items():
user.k = v
user.save()
return UpdateUser(user=user)
But still, I'm also finding some elegant way to do it. 🤘
But, if user wanna remove the content from the field, then what will you do since you are checking !None. IMO, the best practice, when we update a data we send all the data with the updated fields. So we don't need to check, is something empty or not.
I'm trying to set the default image in a django model with a function. Te reason is that i generate the image (a qrcode) and i want to save it with a model asociated with the request.user, it is working with the upload_to= but fails with the default, it seems it doesn't get the instance.
The code is:
-- models.py --
from django.db import models
from django.contrib.auth.models import User
import django.utils.timezone as timezone
from myproject.settings import MEDIA_ROOT
import os
def function1(instance, filename):
retun os.path.join(self.uid.username, str(instance.shortname), '.jpg')
def function2(instance):
return os.path.join(MEDIA_ROOT, str(instance.username), 'tmp.jpg')
class MyModel(models.Model):
uid = models.ForeignKey(User)
shortname = models.CharField()
qr = models.FileField(upload_to=function1, default=function2)
this gives the function2() takes exactly 1 argument (0 given)
i also tried to pass uid as parameter to function2 like this:
def function2(uid):
username = uid.username
return os.path.join(MEDIA_ROOT, username, 'tmp.jpg')
class MyModel(models.Model):
uid = models.ForeignKey(User)
shortname = models.CharField()
qr = models.FileField(upload_to=function1, default=function2(uid))
but this won't work too, gives an AttributeError exception:
'ForeignKey' object has no attribute 'username'
Any ideas on how can i tell django to upload a locally generated file (generated on the django machine at MEDIA_ROOT/request.user.username/)
Thanks!!
I found a way to solve my problem from views here:
Loading Django FileField and ImageFields from the file system
You need to be using instance instead of self. Also, function2 will not be being passed an instance.
You need to use instance instead of self. self does not exist in function1 and function2 scope:
def function1(instance, filename):
return os.path.join(instance.uid.username, str(instance.shortname), '.jpg')
def function2(instance):
return os.path.join(MEDIA_ROOT, str(instance.username), 'tmp.jpg')
class MyModel(models.Model):
uid = models.ForeignKey(User)
shortname = models.CharField()
qr = models.FileField(upload_to=function1, default=function2)
You can found docs for FileField.upload_to here
You get function2() takes exactly 1 argument, (0 given) because function2 is expecting for instance param, and if you try to pass uid like this:
class MyModel(models.Model):
uid = models.ForeignKey(User)
shortname = models.CharField()
qr = models.FileField(upload_to=function1, default=function2(uid))
will raise an error because at this point uid is a models.ForeignKey instance. You could try to do this in a pre_save signal:
def function2(sender, instance, *args, **kwargs):
if not instance.qr:
instance.qr = os.path.join(MEDIA_ROOT, username, 'tmp.jpg')
pre_save.connect(function2, sender=MyModel)
I'm building a Django app to pull in data via an API to track live results of an event with the added ability to override that data before it is displayed.
The first task of the app is to make a request and store the response in the database so I've setup a model;
class ApiData(models.Model):
event = models.CharField(
_("Event"),
max_length=100,
)
key = models.CharField(
_("Data identifier"),
max_length=255,
help_text=_("Something to identify the json stored.")
)
json = JSONField(
load_kwargs={'object_pairs_hook': collections.OrderedDict},
blank=True,
null=True,
)
created = models.DateTimeField()
Ideally I would like it so that objects are created in the admin and the save method populates the ApiData.json field after creating an API request based on the other options in the object.
Because these fields would have choices based on data returned from the API I wanted to lazy load the choices but at the moment I'm just getting a standard Charfield() in my form.
Is this the correct approach for lazy loading model field choices? Or should I just create a custom ModelForm and load the choices there? (That's probably the more typical approach I guess)
def get_event_choices():
events = get_events()
choices = []
for event in events['events']:
choices.append((event['name'], event['title']),)
return choices
class ApiData(models.Model):
# Fields as seen above
def __init__(self, *args, **kwargs):
super(ApiData, self).__init__(*args, **kwargs)
self._meta.get_field_by_name('event')[0]._choices = lazy(
get_event_choices, list
)()
So I went for a typical approach to get this working by simply defining a form for the model admin to use;
# forms.py
from django import forms
from ..models import get_event_choices, ApiData
from ..utils.api import JsonApi
EVENT_CHOICES = get_event_choices()
class ApiDataForm(forms.ModelForm):
"""
Form for collecting the field choices.
The Event field is populated based on the events returned from the API.
"""
event = forms.ChoiceField(choices=EVENT_CHOICES)
class Meta:
model = ApiData
# admin.py
from django.contrib import admin
from .forms.apidata import ApiDataForm
from .models import ApiData
class ApiDataAdmin(admin.ModelAdmin):
form = ApiDataForm
admin.site.register(ApiData, ApiDataAdmin)
I have an app that I'm calling Progress. I want to have several different apps throughout my project write to it whenever something happens. But all the different apps are not the same in how they broadcast progress. So I thought that a ContentType solution would work.
The only trick that I'm having a hard time figuring out is that I need to write to the Progress app when an event occurs. Such as when a view renders. I've been trying get_or_create but I'm having trouble getting the right configuration in the queryset. Any suggestions for how to correct this?
I want the get_or_create to sit in the view of an app so that the action I want is what writes to the progress.
My Progress Model.py
from django.db import models
from django.template.defaultfilters import slugify
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from datetime import datetime
class Progress(models.Model):
"""
The page log. Records the user and the object.
"""
user = models.ForeignKey(User, related_name='user_pagelog')
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
stamp = models.DateTimeField(auto_now_add=True)
class Meta:
unique_together = (('user', 'content_type', 'stamp'),)
verbose_name = 'View Log'
verbose_name_plural = 'View Logs'
get_latest_by = 'stamp'
def __str__(self):
return "%s got to %s on %s" % (self.user, self.content_type, self.stamp)
#classmethod
def get_latest_view(cls, user):
"""
Get most recent view log value for a given user.
"""
try:
view_log = cls.objects.filter(user=user).order_by('-stamp')[0]
return view_log.value
except IndexError:
return None
An example of the queryset that I want to write to the Progress app:
Progress.objects.get_or_create(user=request.user, content_type=f.id)
Where f = get_object_or_404(Page, publish=True)
Finally, the error I'm getting:
Cannot assign "1": "Progress.content_type" must be a "ContentType" instance.
Which I think it means the instance isn't getting found? But it exists, so I'm confused.
Thanks.
No, it doesn't mean that at all. It means what it says, that the parameter has to be an instance of the ContentType model, whereas you're passing the ID of the object itself.
You might be able to use content_type along with the actual instance:
Progress.objects.get_or_create(user=request.user, content_object=f)
Otherwise you'll need to get the right ContentType using the get_for_model() method, and pass that along with the object id.