Im working on a django application and I can't seem to get this one piece of code working. I know of some hacky ways to accomplish my task, but it seems like there should be a better way. I have a model class with one field in it:
class MobileUser(models.Model):
phone_id = models.AutoField(primary_key=True)
and everything is groovy. However, when I want to create an instance of the class and save it to the database like so:
mobile = MobileUser()
mobile.save()
I get a warning saying that MobileUser has no default value arguments, which makes sense. I know I can do things like get the last inserted row/the max id + 1 and pass that in as an argument but I'd prefer not to do that. Any ideas? Oh, and side note, the operation works it just throws a warning.
Why not let django handle it then, just do this:
class MobileUser(models.Model):
pass
Whenever you create an entry it would auto increment the id field.
Related
I am defining a field in a django form in the following two ways :
class MyForm(forms.Form):
myfield = forms.ChoiceField(choices=[(u.id,u.username) for u in User.objects.filter(type="TYPE1")])
OR
class MyForm(forms.Form):
pass
def_init_(self,*args,**kwargs):
super(MyForm,self)._init_(*args,**kwargs)
self.fields['myfield'] = forms.ChoiceField(choices=[(u.id,u.username) for u in User.objects.filter(type="TYPE1")])
Is there any different between these two approaches?? I tried to find this on web but did not get any relevant answers.
First of all, there is a special field to handle such things - ModelChoiceField
In your example the difference is the moment when code is executed.
In first approach it is executed when module with form is loaded, in second - every time the form is initialized (so basically on each request to your view). So first approach has a problem - Users will be loaded on first request. If any user registers after this moment - he will not be present in the select field until you restart the server.
Also I think it is a bad practice to introduce new field in __init__ method. If you really need something like this and you can't use ModelChoiceField the better way is
class MyForm(forms.Form):
myfield = forms.ChoiceField()
def __init__(self,*args,**kwargs):
super(MyForm,self).__init__(*args,**kwargs)
self.fields['myfield'].choices = [(u.id, u.username) for u in User.objects.filter(type="TYPE1")]
Don't you get an error when you run your server using the first way?
class MyForm(forms.Form):
myfield = forms.ChoiceField(choices=[(u.id,u.username) for u in User.objects.filter(type="TYPE1")])
If you use this method That for will be executed when the file is being read. Try using the second way or a function to execute that for and set the choices.
Usually in Form.__init__ you define some dynamic fields (for example, you want to show some checkboxes, which are set/unset according to the data from some model). In all other cases first approach is better because it's more readable.
I think I have a pretty common use case and am surprised at how much trouble it's giving me.
I want to use a key-value pair for a ReferenceField in the Flask-Admin edit form generated by the following two classes:
class Communique(db.Document):
users = db.ListField(db.ReferenceField(User), default=[])
class User(db.Document):
email = db.StringField(max_length=255, required=True)
def __unicode__(self):
return '%s' % self.id
I want the select to be constructed out of the ObjectId and the an email field in my model.
By mapping the __unicode__
attribute to the id field I get nice things on the mongoengine side like using the entire object in queries:
UserInformation.objects(user=current_user)
This has the unfortunate effect of causing the Flask-Admin form to display the mongo ObjectId in the edit form like so:
The docs say I have to provide the label_attr to the ModelSelectMultipleField created by Flask-Admin. I've done so by overriding the get_form method on my ModelView:
def get_form(self):
form = super(ModelView, self).get_form()
form.users = ModelSelectMultipleField(model=User,
label_attr='email',
widget=form.users.__dict__['kwargs']['widget'])
return form
I'm reusing the the widget used by the original form.users (which may be wrong). It works fine when editing an existing item, BUT throws an exception when creating a new one (perhaps because I'm reusing the widget).
All of this seems like way more work than should be needed to simply provide a label_attr to my SelectField. Fixing up the listing view was a simple matter of adding an entry to the column_formatters dictionary. Is there no simple way to specify the label_attr when creating my ModelView class?
I know I could make this problem go away by returning the email property in the __unicode__ attribute, but I feel like I shouldn't have to do that! Am I missing something?
Oy, now I see how to do it, though it's not that obvious from the docs. form_args is a dictionary with items keyed to the form models. All I needed to do was...
form_args = dict(users=dict(label_attr='email'))
Which does seem about the right amount of effort (considering Flask-Admin isn't some sort of java framework).
I have a legacy database with non-django naming conventions. If I have the following (cut down) models:
class Registration(models.Model):
projectId=models.IntegerField(primary_key=True)
class Application(models.Model):
applicationId=models.IntegerField(primary_key=True)
registration=models.ForeignKey(Registration,db_column='projectId')
The ForeignKey instance causes a property to be created on Application called registration_id, but this is neither the correct name for the field (I have a hack to fix this), nor is it able to be used in a QuerySet.
Is there some way of using the id field provided by the ForeignKey on the Application model, rather than having to reference it via Registration?
Ie. I write lots of code like:
Application.objects.get(projectId=1234)
And don't want to have to write it out as:
Application.objects.get(registration__projectId=1234)
or even
Application.objects.get(registration__pk=1234)
I'm slightly surprised that:
Application.objects.get(registration_id=1234)
doesn't work...
Also note, I tried defining the id column as a field as well as the foreignkey which worked for queryset, but inserts complain of trying to insert into the same column twice:
class Application(models.Model):
...
projectId=models.IntegerField()
...
Have you tried this?
Application.objects.get(registration=1234)
I think just doing Application.objects.registration.get(projectId=1234) should do what you want.
I'm setting up a data model in django using multiple-table inheritance (MTI) like this:
class Metric(models.Model):
account = models.ForeignKey(Account)
date = models.DateField()
value = models.FloatField()
calculation_in_progress = models.BooleanField()
type = models.CharField( max_length=20, choices= METRIC_TYPES ) # Appropriate?
def calculate(self):
# default calculation...
class WebMetric(Metric):
url = models.URLField()
def calculate(self):
# web-specific calculation...
class TextMetric(Metric):
text = models.TextField()
def calculate(self):
# text-specific calculation...
My instinct is to put a 'type' field in the base class as shown here, so I can tell which sub-class any Metric object belongs to. It would be a bit of a hassle to keep this up to date all the time, but possible. But do I need to do this? Is there some way that django handles this automatically?
When I call Metric.objects.all() every objects returned is an instance of Metric never the subclasses. So if I call .calculate() I never get the sub-class's behavior.
I could write a function on the base class that tests to see if I can cast it to any of the sub-types like:
def determine_subtype(self):
try:
self.webmetric
return WebMetric
except WebMetric.DoesNotExist:
pass
# Repeat for every sub-class
but this seems like a bunch of repetitious code. And it's also not something that can be included in a SELECT filter -- only works in python-space.
What's the best way to handle this?
While it might offend some people's sensibilities, the only practical way to solve this problem is to put either a field or a method in the base class which says what kind of object each record really is. The problem with the method you describe is that it requires a separate database query for every type of subclass, for each object you're dealing with. This could get extremely slow when working with large querysets. A better way is to use a ForeignKey to the django Content Type class.
#Carl Meyer wrote a good solution here: How do I access the child classes of an object in django without knowing the name of the child class?
Single Table Inheritance could help alleviate this issue, depending on how it gets implemented. But for now Django does not support it: Single Table Inheritance in Django so it's not a helpful suggestion.
But do I need to do this?
Never. Never. Never.
Is there some way that django handles this automatically?
Yes. It's called "polymorphism".
You never need to know the subclass. Never.
"What about my WebMetric.url and my TextMetric.text attributes?"
What will you do with these attributes? Define a method function that does something. Implement different versions in WebMetric (that uses url) and TextMetric (that uses text).
That's proper polymorphism.
Please read this: http://docs.djangoproject.com/en/1.2/topics/db/models/#abstract-base-classes
Please make your superclass abstract.
Do NOT do this: http://docs.djangoproject.com/en/1.2/topics/db/models/#multi-table-inheritance
You want "single-table inheritance".
I have the following in my model:
class info(models.Model):
add = models.CharField(max_length=255)
name = models.CharField(max_length=255)
An in the views when i say
info_l = info.objects.filter(id=1)
logging.debug(info_l.name)
i get an error saying name doesnt exist at debug statement.
'QuerySet' object has no attribute 'name'
1.How can this be resolved.
2.Also how to query for only one field instead of selecting all like select name from info.
1. Selecting Single Items
It looks like you're trying to get a single object. Using filter will return a QuerySet object (as is happening in your code), which behaves more like a list (and, as you've noticed, lacks the name attribute).
You have two options here. First, you can just grab the first element:
info_l = info.objects.filter(id=1)[0]
You could also use the objects.get method instead, which will return a single object (and raise an exception if it doesn't exist):
info_l = info.objects.get(id=1)
Django has some pretty good documentation on QuerySets, and it may be worth taking a look at it:
Docs on using filters
QuerySet reference
2. Retrieving Specific Fields
Django provides the defer and only methods, which will let you choose specific fields from the database, rather than fetching everything at once. These don't actually prevent the fields from being read; rather, it loads them lazily. defer is an "opt-in" mode, which lets you specify what fields should be lazily loaded. only is "out-out" -- you call it, and only the fields you pass will by eagerly loaded.
So in your example, you'd want to do something like this:
info_l = info.objects.filter(id=1).only('name')[0]
Though with a model as simple as the example you give, I wouldn't worry much at all about limiting fields.