Models.py
#.....
class FilterSave(models.Model):
def __unicode__(self):
return "%s" % (self.name)
name = models.CharField(max_length=50)
customer_type = models.CharField(max_length=20)
tag = models.CharField(max_length=10)
In my views.py
#......
def save_filter(self, filter_name, keyword_filter):
dict_json = eval(json.dumps(keyword_filter))
filter_saves = FilterSave.objects.all()
# Avoid record that already exist
filter_save = FilterSave(name=filter_name, customer_type=dict_json["customer_type"], tag=dict_json["tag"])
# I am trying ....
for fs in filter_saves:
if fs.name != filter_name:#just check for a field name
filter_save.save()
else:
print 'already exist '
More I tried
# Avoid name collision(just for name field not for a Record)
filter_save = FilterSave(name=filter_name, customer_type=dict_json["customer_type"], tag=dict_json["tag"])
exists = FilterSave.objects.filter(name=filter_name)
if not exists:
filter_save.save()
My problems here .I want to save a RECORD if it's not exist in table.Anybody Could help me what I am trying here?
thanks
Django has a convenience method get_or_create(defaults=None, **kwargs)
get_or_create
A convenience method for looking up an object with the given kwargs (may be empty if your model has defaults for all fields), creating one if necessary.
Returns a tuple of (object, created), where object is the retrieved or created object and created is a boolean specifying whether a new object was created.
Is that what you mean?
Related
I am getting empty in return (from my model methods), I don't get where I am wrong in this, we can query model using self
class SocialLinks(models.Model):
alias_name = models.CharField(max_length=10,)
name = models.CharField(max_length=30)
url_link = models.URLField()
def get_fb_link(self):
try:
fb = self.objects.get(alias_name='fb')
return fb.url_link
except:
return ""
def get_linkdin_link(self):
try:
linkdin = self.objects.get(alias_name='linkedin')
return linkdin
except:
return ""
def get_insta_link(self):
try:
insta = self.objects.get(alias_name='insta')
return insta.url_link
except:
Your issue is that self corresponds to one instance of the model class, not the class itself.
So you can do
all_fb_links = SocialLinks.objects.filter(alias_name="fb")
and you will get all the records from the model that are facebook links, but you cannot do this referencing a single instance of the record using self.
You could write a class method, but what you actually want here is a model manager to define some specific queries so that you can then do
SocialLinks.get_all_fb_links()
Here's the docs on defining a custom manager: https://docs.djangoproject.com/en/3.2/topics/db/managers/
A method on the class like you are defining would be used to return something not stored on the table, but which could perhaps be derived from it. A simple example might be:
def link_type_and_url(self):
return f"{self.alias_name}:{url_link}"
I following up with my question Creating new objects under specific parameters . I was trying to find out how to write functions into my django models to create default values on fields. I know how to do that, but now would like to take it a step further by adding parameters to the functions and using previous fields as the parameters. So far I have tried the following and each have given their own error messages when I try and migrate them.
class NewTest(models.Model):
score = models.IntegerField(default=0)
def num(score): # Want the score parameter to be the score field
new_num = score
return new_num
last_score = models.IntegerField(default=num(score))
Error: int() argument must be a string, a bytes-like object or a number, not 'IntegerField'
class NewTest(models.Model):
score = models.IntegerField(default=0)
def num(self):
new_num = self.score
return new_num
last_score = models.IntegerField(default=num(self))
NameError: name 'self' is not defined
class NewTest(models.Model):
score = models.IntegerField(default=0)
def num():
new_num = self.score
return new_num
last_score = models.IntegerField(default=num)
NameError: name 'self' is not defined
Does anybody know how to do this, or know where there is documentation on this?
Django's model field default callable can't actually be an instance method. Due to how this callable is used in migrations it must be serializable for migrations, e.g. in the migrations you'll see a reference to the path of the function, such as default="my_app.models.my_callable_default".
The way I've seen other solve this is to override the models save method to check those fields and set the default value there.
class NewTest(models.Model):
score = models.IntegerField(default=0)
last_score = models.IntegerField(default=0)
def save(self, *args, **kwargs):
if not self.pk: # Check for create
self.last_score = self.score
else:
# Get the existing score from the database, because this instance has been modified
score_from_db = NewTest.objects.values("score").get(pk=self.pk)["score"]
self.last_score = self.score
return super().save(*args, **kwargs) # Continue with save as normal
This solution overrides the save method of your model to assign another fields value to the last_score field during creation, and if it's an update it will pull the existing object from the database to get the last score (I'm not sure if this is what you are after). The if not self.pk is used to check if the current save is being called for a new object (create), or an existing object (update), because the database assigns the primary key during creation.
my models.py
class WebFieldType(models.Model):
WEBFIELD_CHOICES = ( ('FACEBOOK', 'fb'), ('INSTAGRAM', 'Insta') )
webfield_type = models.CharField(null=True, blank=True, max_length=30, choices=WEBFIELD_CHOICES)
def __unicode__(self):
return '{}'.format(self.webfield_type)
class WebTokens(models.Model):
token_name = models.TextField()
web_field_type = models.ManyToManyField(WebFieldType)
def __unicode__(self):
return '{}-{}'.format(self.token_name,self.web_field_type )
Now in shell if I do like:
WebFieldType.objects.all().values('webfield_type'), it is returning [{'webfield_type' : 'FACEBOOK'}, {'webfield_type' : 'INSTAGARAM'}]
But if I do like
WebTokens.objects.all().values('token_name','web_field_type') it is returning
[{'token_name' : 'some_token_name', 'web_field_type' : 1}]
As you can see in web_field_type it is returning id, but I need name.
Even tried using return '{}'.format(self.get_webfield_type_display()) in WebTokens model but in vain.
So basically I need everything that is stored in WebTokens model when I make a call to it.
You did not specify what is template_name attribute in the WebTokens model. But I'll try to get your point. What are doing is that you take the values from ManyToMany field which is in your case web_field_type: 1. So if you want to get all vallues from the model and serialize it, then it would be more complicated than this. Consider creating method in WebTokens model.
EDITED
#property
def web_field_type_types(self):
names = list()
for obj in self.web_field_type.all():
names.append(obj.get_type_display())
return str(names)
And then using it in your queries so you can get string of ids with
webtoken.web_field_type_types
This is a hard question for me to describe, but I will do my best here.
I have a model that is for a calendar event:
class Event(models.Model):
account = models.ForeignKey(Account, related_name="event_account")
location = models.ForeignKey(Location, related_name="event_location")
patient = models.ManyToManyField(Patient)
datetime_start = models.DateTimeField()
datetime_end = models.DateTimeField()
last_update = models.DateTimeField(auto_now=False, auto_now_add=False, null=True, blank=True)
event_series = models.ForeignKey(EventSeries, related_name="event_series", null=True, blank=True)
is_original_event = models.BooleanField(default=True)
When this is saved I am overriding the save() method to check and see if the event_series (recurring events) is set. If it is, then I need to iteratively create another event object for each recurring date.
The following seems to work, though it may not be the best approach:
def save(self, *args, **kwargs):
if self.pk is None:
if self.event_series is not None and self.is_original_event is True :
recurrence_rules = EventSeries.objects.get(pk=self.event_series.pk)
rr_freq = DAILY
if recurrence_rules.frequency == "DAILY":
rr_freq = DAILY
elif recurrence_rules.frequency == "WEEKLY":
rr_freq = WEEKLY
elif recurrence_rules.frequency == "MONTHLY":
rr_freq = MONTHLY
elif recurrence_rules.frequency == "YEARLY":
rr_freq = YEARLY
rlist = list(rrule(rr_freq, count=recurrence_rules.recurrences, dtstart=self.datetime_start))
for revent in rlist:
evnt = Event.objects.create(account = self.account, location = self.location, datetime_start = revent, datetime_end = revent, is_original_event = False, event_series = self.event_series)
super(Event, evnt).save(*args, **kwargs)
super(Event, self).save(*args, **kwargs)
However, the real problem I am finding is that using this methodology and saving from the Admin forms, it is creating the recurring events, but if I try to get self.patient which is a M2M field, I keep getting this error:
'Event' instance needs to have a primary key value before a many-to-many relationship can be used
My main question is about this m2m error, but also if you have any feedback on the nested saving for recurring events, that would be great as well.
Thanks much!
If the code trying to access self.patient is in the save method and happens before the instance has been saved then it's clearly the expected behaviour. Remember that Model objects are just a thin (well...) wrapper over a SQL database... Also, even if you first save your new instance then try to access self.patient from the save method you'll still have an empty queryset since the m2m won't have been saved by the admin form yet.
IOW, if you have something to do that depends on m2m being set, you'll have to put it in a distinct method and ensure that method get called when appropriate
About your code snippet:
1/ the recurrence_rules = EventSeries.objects.get(pk=self.event_series.pk) is just redundant, since you alreay have the very same object under the name self.event_series
2/ there's no need to call save on the events you create with Event.objects.create - the ModelManager.create method really create an instance (that is: save it to the database).
I am trying to create a custom cleaning method which look in the db if the value of one specific data exists already and if yes raises an error.
I'm using a model form of a class (subsystem) who is inheriting from an other class (project).
I want to check if the sybsystem already exists or not when i try to add a new one in a form.
I get project name in my view function.
class SubsytemForm(forms.ModelForm):
class Meta:
model = Subsystem
exclude = ('project_name')
def clean(self,project_name):
cleaned_data = super(SubsytemForm, self).clean(self,project_name)
form_subsystem_name = cleaned_data.get("subsystem_name")
Subsystem.objects.filter(project__project_name=project_name)
subsystem_objects=Subsystem.objects.filter(project__project_name=project_name)
nb_subsystem = subsystem_objects.count()
for i in range (nb_subsystem):
if (subsystem_objects[i].subsystem_name==form_subsystem_name):
msg = u"Subsystem already existing"
self._errors["subsystem_name"] = self.error_class([msg])
# These fields are no longer valid. Remove them from the
# cleaned data.
del cleaned_data["subsystem_name"]
return cleaned_data
My view function :
def addform(request,project_name):
if form.is_valid():
form=form.save(commit=False)
form.project_id=Project.objects.get(project_name=project_name).id
form.clean(form,project_name)
form.save()
This is not working and i don't know how to do.
I have the error : clean() takes exactly 2 arguments (1 given)
My model :
class Project(models.Model):
project_name = models.CharField("Project name", max_length=20)
Class Subsystem(models.Model):
subsystem_name = models.Charfield("Subsystem name", max_length=20)
projects = models.ForeignKey(Project)
There are quite a few things wrong with this code.
Firstly, you're not supposed to call clean explicitly. Django does it for you automatically when you call form.is_valid(). And because it's done automatically, you can't pass extra arguments. You need to pass the argument in when you instantiate the form, and keep it as an instance variable which your clean code can reference.
Secondly, the code is actually only validating a single field. So it should be done in a specific clean_fieldname method - ie clean_subsystem_name. That avoids the need for mucking about with _errors and deleting the unwanted data at the end.
Thirdly, if you ever find yourself getting a count of something, iterating through a range, then using that index to point back into the original list, you're doing it wrong. In Python, you should always iterate through the actual thing - in this case, the queryset - that you're interested in. However, in this case that is irrelevant anyway as you should query for the actual name directly in the database and check if it exists, rather than iterating through checking for matches.
So, putting it all together:
class SubsytemForm(forms.ModelForm):
class Meta:
model = Subsystem
exclude = ('project_name')
def __init__(self, *args, **kwargs):
self.project_name = kwargs.pop('project_name', None)
super(SubsystemForm, self).__init__(*args, **kwargs)
def clean_subsystem_name(self):
form_subsystem_name = self.cleaned_data.get("subsystem_name")
existing = Subsystem.objects.filter(
project__project_name=self.project_name,
subsytem_name=form_subsystem_name
).exists()
if existing:
raise forms.ValidationError(u"Subsystem already existing")
return form_subsystem_name
When you do form=form.save(commit=False) you store a Subsystem instance in the variable form but the clean method is defined in SubsystemForm. Isn't it?