Add to ManyToMany Ahead of Time - django

Supposing I have a model in Django with a manytomany field.
class MyModel(models.Model):
m2m_field = models.ManyToMany(OtherModel)
class OtherModel(models.Model):
some_text = models.CharField(max_length=256)
If I list MyModel's attributes, there is no m2m_field until I save it.
>>> my_model.m2m_field
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Library/Python/2.7/site-packages/django/db/models/fields/related.py", line 897, in __get__
through=self.field.rel.through,
File "/Library/Python/2.7/site-packages/django/db/models/fields/related.py", line 586, in __init__
(instance, source_field_name))
ValueError: "<MyModel>" needs to have a value for field "mymodel" before this many-to-many relationship can be used.
Okay, fair enough. So I call my_model.save(), and then I get a RelatedManager object on my_model.m2m_field and I can call my_model.m2m_field.add(other_model_instance).
But.... is there any way to do this in advance? Sometimes it's not so great to post something without certain fields.

I am not totally sure about your question but I think you want to look into post save on the dependent object:
http://www.djangofoo.com/tag/post_save
The idea being that you can save an OtherModel automagically whenever a MyModel is saved?
Feel free to clarify if I have missed your point.

Related

Django: avoid RelatedObjectDoesNotExist for new objects

I have a question regarding Django to which I already have a work-around; but I simply find it hard to believe that this is the actual idiom, so I'm very much open to better suggestions.
Consider de following models:
class Experiment(models.Model):
not_null = models.ForeignKey("self", null=False)
nullable = models.ForeignKey("self", null=True)
And the following REPL-session:
>>> Experiment().not_null is None
Traceback (most recent call last):
File "<console>", line 1, in <module>
[..]
RelatedObjectDoesNotExist: Experiment has no not_null.
>>> Experiment().not_null_id is None
True
>>> Experiment().nullable is None
True
My concern is about the first line of the REPL-session failing. I'd like to be able to check for proper initialization, but I cannot do so idiomatically.
My surprise is about the following: Django raises a DB-related exception (suggesting that there was actually an attempt to look this up in the DB); whereas there would be no need to actually go to the DB to figure out the field is not set. I don't want to be forced to catch an exception that shouldn't have been raised in the first place.
As evidenced, you can work around this by postpending _id, but this is a hack IMHO.
now for the question:
Is there a more idiomatic way to figure out whether a non-nullable field has already been set on newly created object?
I cannot find this in the documentation.

Why does Django Queryset say: TypeError: Complex aggregates require an alias?

I have a Django class as follows:
class MyModel(models.Model):
my_int = models.IntegerField(null=True, blank=True,)
created_ts = models.DateTimeField(default=datetime.utcnow, editable=False)
When I run the following queryset, I get an error:
>>> from django.db.models import Max, F, Func
>>> MyModel.objects.all().aggregate(Max(Func(F('created_ts'), function='UNIX_TIMESTAMP')))
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "MyVirtualEnv/lib/python2.7/site-packages/django/db/models/query.py", line 297, in aggregate
raise TypeError("Complex aggregates require an alias")
TypeError: Complex aggregates require an alias
How do I adjust my queryset so that I don't get this error?
I want to find the instance of MyModel with the latest created_ts. And I want to use the UNIX_TIMESTAMP function to get it.
I'm not running the same Django version, but I think this'll work:
MyModel.objects.all().aggregate(latest=Max(Func(F('created_ts'), function='UNIX_TIMESTAMP')))
Note the latest keyword argument in there. That's the key (I think, again I can't test this).
From the django docs:
aggregate() is a terminal clause for a QuerySet that, when invoked,
returns a dictionary of name-value pairs
It will automatically provide this value in many generic cases, e.g.
Sum('items') -> sum_items
For your query, it cannot create a default alias, so you must provide one. This is so the query can return a named result for the values produced. All you have to do is give your aggregate a meaningful named alias and all should work fine:
MyModel.objects.all().aggregate(max_created=Max(Func(F('created_ts'), function='UNIX_TIMESTAMP')))
just need set name for result variable :
see item in below code
result = MyModel.objects.all().aggregate(item=Max(Func(F('created_ts'), function='UNIX_TIMESTAMP')))
result.get('item')

Django use model EmailField raising AttributeError

I've added a model boolean field called 'is_dotcom' to my admin list_display, and the implementation is:
email = models.EmailField(max_length=254)
def is_dotcom(self):
return self.email.lower().endsWith(".com")
is_dotcom.admin_order_field = 'email'
is_dotcom.boolean = True
is_dotcom.short_description = 'Company?'
But all this yields on my admin page is "(None)". I'm expecting True/False (though sometimes my booleans show as a green check or red no entry sign, anyone know why that is?)
I've based this code on an example in the django tutorial.
I'm assuming that "(None)" is being shown because the is_dotcom() method is raising an AttributeError which django is catching. I'm guessing that it's legal to call .lower() on an EmailField but I don't know for sure (what do you guys do for reference documentation?) Thanks.
The problem is in this line:
return self.email.lower().endsWith(".com")
The method is .endswith().
Please note the absence of camel-case.
A simplified example which reproduces the error:
>>> 'foo'.endsWith('test')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'endsWith'

object has no attribute 'exists'

I am using Django 1.3 and trying to use .exists() on a model entry but get the error listed below. Exists() was included in Django 1.2 so I should have access to it. I verified my version using django.get_version and it was okay.
Querying MyModel based on pk only returns an entry but querying with .exists() throws an error. Do I need to imports something?
>>> m = MyModel.objects.get(pk=1)
>>> m
<MyModel: Model field entry 1>
>>> m = MyModel.objects.get(pk=1).exists()
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'MyModel' object has no attribute 'exists'
exists() is a method of a QuerySet.
get() returns a single model instance, and will raise an exception Entry.DoesNotExist if that instance doesn't exist. So you'll need to wrap this in a try/except block if you're not sure if an instance with that id exists.
I'm using Django 1.7 on my project and my codes like :
try:
temp_query_set = YourModelName.functionName()
except ObjectDoesNotExists:
<do something>
note that, my code (at first) using if query_set.exists()
it works fine when there is no query set returned, but raise error object does not have attribute 'exists' when there is something returned.
so pls try avoid using if <something>.exists()
CMIIW
try use .filter() instead .get(), like this:
m = MyModel.objects.filter(pk=1).exists()
y = MyModel.objects.filter(pk=2).exists()
print(m)
print(y)
output must to be a bool, exemple:
False
True
suposing that m does not exist and y exists

Django: How can you validate a model if the __init__() just raises errors as soon as you feed it data?

Let's say I have a CarModel(models.Model) that uses price = models.DecimalField():
import CarModel
car = CarModel(name='Corvette', price='Hello World')
Traceback (most recent call last):
...
ValidationError: 'price needs to be a Decimal()'
The error was basically that.
Since the price was expecting a decimal but received a string, it raises a ValidationError immediately.
I was expecting it to work like this:
car = CarModel(name='Corvette', price='Hello World')
car.full_clean()
Traceback (most recent call last):
...
ValidationError: 'price needs to be a Decimal()'
Im I thinking about this correctly? Does it seem like ValidationError should only be raised on save() or by explicitly calling full_clean()?
Instances are not saved until you do save(). That being said the issue is one init django tries to do proper coercion, turning all your values into the right datatypes. In this case the data can't even be coerced properly, so Django gives you an exception right away. I realize the distinction may seem a bit nebulous, but if it wasn't this way you could be getting a DecimalField off of a model without getting a Decimal object.