I've come across the following line of code
_, created = UserProfile.objects.update_or_create(
What is the point of the "_"?
Thanks!
update_or_create returns a tuple. The first value is the object, the second value is a bool that is True if the object is created and False if it was updated.
https://docs.djangoproject.com/en/3.1/ref/models/querysets/
_ is a variable that is commonly used in python to denote this particular value is being ignored.
.update_or_create(…) [Django-doc] returns a 2-tuple:
Returns a tuple of (object, created), where object is the created or updated object and created is a boolean specifying whether a new object was created.
Here one uses iterable unpacking [pep-3132] to unpack the 2-tuple and assign the first and second value of the 2-tuple to a variable named _ and created respectively.
Often variables like _ and __ are used for values for which we are not interested. It is thus used as a "throwaway" variable that is necessary to unpack the 2-tuple.
Here likely the rest of the function is only interested in the value for created, not in the created or updated object.
Related
I am trying to use get_or_create method to see if a record exists. If the record exists do nothing otherwise create it.
This model is basically used on the command that is failing
class modelStudentExamsPerformed(models.Model):
patient = models.ForeignKey(modelPatient)
student = models.ForeignKey(modelStudent,on_delete=models.CASCADE)
normalBodyPart = models.ForeignKey(modelNormalBodyPartResult,default=None,blank=True,null=True)
abnormalBodyPart = models.ForeignKey(modelAbnormalBodyPartResult,default=None,blank=True,null=True)
tool = models.CharField(max_length=128, default="")
Now this is the command that is using the above model and failing
exams.modelStudentExamsPerformed.objects.get_or_create()(patient=patient_qset, student=stud_qset,abnormalBodyPart=qset[0],normalBodyPart=None,date=None)
The above statement gives me the error :
get() returned more than one modelStudentExamsPerformed -- it returned 2!
Now this is where I am having trouble. When I look into the database through my admin I do notice two objects but those objects both have a value associated with normalBodyPart and their abnormalBodyPart is empty.Since I explicitly specified and assigned a value to abnormalBodyPart why does django say that two items already exist ? I hope this makes sense .
Let e explain this another way as well suppose there are two statements 1 and 2.
Statement 1 gets or creates a record based on a specified parameter . This get or create fails as django thinks there are already two records. However statement 2 uses the same exact parameters and returns 0 records. Why is that ? What am I missing and not understanding here ?
Statement 1:
exams.modelStudentExamsPerformed.objects.get_or_create()(patient=patient_qset, student=stud_qset,abnormalBodyPart=qset[0],normalBodyPart=None,date=None)
when clearly none of the objects in this table have a value for abnormalBodyPart. I validated this by doing the following
Statement 2:
k = exams.modelStudentExamsPerformed.objects.filter(patient=patient_qset, student=stud_qset,abnormalBodyPart=qset[0], normalBodyPart=None,date=None)
The above statment 2 does not return anything. My question is why does Statement 2 not return anything while statement 1 is complaining that there are 2 items already thus failing the get call.
You're invoking get_or_create() without arguments and then invoke the __call__() method on the resulting instance.
Put the keywords inside the get_or_create to make it work properly. Also study the method signature again: you're missing a defaults argument. The method works like this:
Filter on provided keyword arguments, except "defaults"
If nothing is returned, create a new instance with those keyword arguments and use the "defaults" keyword argument, which should be a dictionary to fill additional fields.
Sometimes, it's better to illustrate:
instance, created = Players.objects.get_or_create(
username='Lagolas',
defaults={'class': 'ranger', 'gender': 'male'}
)
Is equivalent to:
try:
instance = Players.objects.get(username='Lagolas')
return instance, False
except Players.DoesNotExist:
instance = Players.objects.create(
username='Lagolas', class='ranger', gender='male'
)
return instance, True
How do I filter by just empty value? I can do this:
Name.objects.filter(alias__isnull=False)
But it will not work because it's just empty inside the column with no value. How can I filter by that?
If I understand the question you want all Name objects, except ones where alias is None or ''. You can do that with: Name.objects.filter(alias__isnull=False).exclude(alias__exact='')
If I define a recarray r with a field called data as follows
import numpy
r = numpy.zeros( 1, numpy.dtype([('data', 'f8')]) ).view(numpy.recarray )
the data field will refer to some internal recarray buffer rather than a floating point number. Indeed, running
r.data
yields
<read-write buffer for 0x7f3c10841cf8, size 8, offset 0 at 0x7f3c1083ee70>
rather than [0]. I suspect the reason for the failure is that recarray already has a member called data and hence it just ignores my field called data. The same problem occurs if I try to use any name of already existing members of recarray.
My questions are:
1) Is it possible to circumvent this limitation of recarray and how to do it?
2) Is this limitation likely to be lifted in the future?
Here is the getattribute method for recarray. Python translates obj.par1 to obj.__getattribute__('par1'). This would explain why the field name has to be a valid attribute name, when used in recarrays.
def __getattribute__(self, attr):
try:
return object.__getattribute__(self, attr) #**
except AttributeError: # attr must be a fieldname
pass
fielddict = ndarray.__getattribute__(self, 'dtype').fields
try:
res = fielddict[attr][:2]
except (TypeError, KeyError):
raise AttributeError("record array has no attribute %s" % attr)
obj = self.getfield(*res)
# if it has fields return a recarray, otherwise return
# normal array
if obj.dtype.fields:
return obj
if obj.dtype.char in 'SU':
return obj.view(chararray)
return obj.view(ndarray)
The ** line explains why obj.data returns the buffer pointer, not your field. Same would apply to 'shape' and 'strides'. This also makes it possible to access array methods. You want the recarray to behave as much like a regular array as possible, don't you?
The field names in a structured array are like the keys of a dictionary, relatively free form (though I've never explored the limits). But in recarray, those names have to function also a attribute names. Attributes names have to be valid variable names - that's a Python constraint.
In https://stackoverflow.com/a/32540939/901925 I quote from the genfromtxt docs:
Numpy arrays with a structured dtype can also be viewed as recarray, where a field can be accessed as if it were an attribute. For that reason, we may need to make sure that the field name doesn’t contain any space or invalid character, or that it does not correspond to the name of a standard attribute (like size or shape), which would confuse the interpreter.
Also a tutorial on Python classes says:
Attribute references use the standard syntax used for all attribute references in Python: obj.name. Valid attribute names are all the names that were in the class’s namespace when the class object was created.
https://docs.python.org/2/tutorial/classes.html#tut-object
I understand that get_or_create is now deprecated in favour of using upsert, but how do I make update_one to return the object rather the number of objects modified, and can I just retrieve an object if I don't want to update anything?
e.g.
Model.objects.get_or_create(first_name='John', last_name='Potter', age=40)
# assuming that first_name + last_name + age are enough to uniquiely indentify a person
returns a Model object (a new object if it didn't exist, and existing object if it does). What would be the equivalent of this using the new method?
Model.objects(first_name='John', last_name='Potter', age=40).update_one(upsert=True)
# returns number of objects (1)
Model.objects(first_name='John', last_name='Potter', age=40).update_one(set__first_name='John', set__last_name='Potter', set__age=40,upsert=True)
# returns number of objects (1)
Is there a way to make it return the object, and make it behave exactly like get_or_create?
I couldn't find how to do this in the documentation
You are very close but you need to use a findAndModify command via modify rather than an update command.
NewDoc = Model.objects(first_name='John',
last_name='Potter',
age=40).modify(upsert=True, new=True,
set__first_name='John,
set__last_name='Potter',
set__age=40,
set_on_insert__newUser=True)
Take note of the first 2 modify kwargs - upsert and new. Also take note of the $setOnInsert operator example which will only set a field if the findAndModify does an upsert.
You should look at modify. Passing a new=True you'll get the updated object (or document, in mongodb parlance).
By below line m getting
members = Member.objects.filter(profile=profiles)
i want to pass memeber with field name in this line same as here https://docs.djangoproject.com/en/dev/topics/forms/formsets/#using-initial-data-with-a-formset
member_formset = MemberFormSet(initial=members)
gives me an error
'Member' object is not iterable
please suggest best way to do it ?
Try to pass only one object to initial, e.g. members[0]. Filter returns list of objects.
You don't pass objects as initial to a formset (it's for a dictionary of values). Use queryset=members instead.