Update only some field with create_update.update_object - python

I've defined a models.py with a "FirstClass" which contains a ForeignKey relathionship to "SecondClass". The relathionship can't be Null.
The SecondClass is very expansive (90.000 records), and when i display the FirstClass html form, it requires too many time generating the "select box" field.
Therefore, when I let user update the object (I use create_update.update_object generic view), i don't want to display and update the value of the foreignkey field, but i don't know how to do this...

Create a ModelForm and pass it into the view, according to the docs.
Since the foreign key should always exist upon creation, it's safe to ignore it in the update.
class MyModelForm(forms.ModelForm):
class Meta:
model = FirstClass
exclude = ('SecondClass',)
# urls.py
(r'^foo/(?P<object_id>\d+)/$','django.views.generic.create_update.update_object',
{'form_class': MyModelForm})

Related

Django ManyToMany Field Not Accepting Correct Model

I'm trying to make a manytomany field from a model that is not the model that the manytomany field will contain a list of. e.g.
class Following(models.Model):
following_id = models.AutoField(primary_key=True)
following_user = models.ForeignKey(User, models.DO_NOTHING, related_name="following_user")
following = models.ManyToManyField(User, related_name="following")
This looks all good to me, but when I try to enter the shell and do something like User.following.add(OtherUser), I get an error saying that it was expecting OtherUser to be an instance of Following. Why is this? Did I not specify that the ManyToManyField was storing User instances when I declared the following variable?
models.ManyToManyField(**User**, related_name="following")
1 - Create a user : user = User(); user.save()
2 - Create a following : following = Following(); following.save()
3 - Add the user to the following : following.following.add(user)
You can reference a model with other model only once. But you are using User model two times, one with following_user field and other with following field. Look below your model.
class Following(models.Model):
following_id = models.AutoField(primary_key=True)
following_user = models.ForeignKey(*User*, models.DO_NOTHING, related_name="following_user")
following = models.ManyToManyField(*User*, related_name="following")
try this:
Another side effect of using commit=False is seen when your model has a many-to-many relation with another model. If your model has a many-to-many relation and you specify commit=False when you save a form, Django cannot immediately save the form data for the many-to-many relation. This is because it isn’t possible to save many-to-many data for an instance until the instance exists in the database.
To work around this problem, every time you save a form using commit=False, Django adds a save_m2m() method to your ModelForm subclass. After you’ve manually saved the instance produced by the form, you can invoke save_m2m() to save the many-to-many form data. For example:

Add extra fields to a ModelAdmin form

So, I have a ModelAdmin that I need to add extra fields to. These fields do not exist on the model, but will be dynamically added to a custom ModelForm through the init method, and logic inside clean will handle the returned data on save.
I can't seem to find any solid information related to adding custom non-model fields to a ModelAdmin form. The closest I have come is by overriding get_fields on the ModelAdmin class and updating self.form.declared_fields with the new fields I'd like to add.
This just doesn't feel very clean to me and I was curious if there was a better way to add new fields to a ModelAdmin dynamically?
You can also use this way to add fields not in the models.py
in admin.py:::
from django.utils.translation import gettext as _
class TrialAdmin(admin.ModelAdmin):
fields = (..., 'non_model_field',...,)
def non_model_field(self, instance):
# this method name should be same as new field name defied above in fields.
# [what u need to do here]
non_model_field.short_description = _("non_model_field")
#This value 'short_description' defines what the field name is shown as in admin similar to 'verbose_name' in models.
admin.site.register(..., TrialAdmin)

Using Django ModelForm with non-persistent model.Field

Is there a way to add a field to a Django model class such that:
It doesn't get persisted to the database (i.e. no column in the DB)
It does get rendered by a ModelForm
The widget for that field can be customised
I believe 3. can be done with a custom widget, and 2. will happen if the field inherits from models.Field. However, I haven't found a way to achieve 1. without breaking 2. and 3. I was hoping for a persist=False or db_column=None type of solution.
Scenario:
I'm using this to quickly produce data capture forms by only adding a class to the model, but in order to insert headers for sub sections I still having to edit the template. Was hoping to do the following:
models.py
from django.db import models
class Applicant(models.Model):
sectionA = models.SectionField(help_text="Personal details")
title = models.CharField(max_length=100)
name = models.CharField(max_length=100)
sectionB = models.SectionField(help_text="Banking details")
account = models.CharField(max_length=100)
pin = models.CharField(max_length=100)
In the above example, sectionA and sectionB are instances of a custom model.Field that doesn't actually get persisted but cause a heading to be rendered by the ModelForm and a custom widget
Finally:
I realise this probably violates separation of View and Model.
Other questions have been asked about non-persisting fields but their solutions don't render in a ModelForm
Sort of, Just don't make them a model field, theres no need for them to be.
sectionA = "Personal details"
sectionB = "Banking details"
You can access them via form.instance where you need them, you could even make them a form field instead of a string as I've shown here.

Django 1.7: how to make ManyToManyField required?

I have a Django Model with ManyToManyField in it. I need to require user to select at least one M2M value in this field.
I tried to set blank=False to M2M field but it didn't help.
class Skill(models.Model):
name = models.CharField(max_length=200)
class PersonSkills(models.Model):
person = models.ForeignKey('Person')
skill = models.ForeignKey('Skill')
class Person(models.Model):
name = models.CharField(max_length=200)
skills = models.ManyToManyField('Skill', through='PersonSkills')
p = Person(name='Bob')
p.save()
# success, but I expect that this should throw ValidationError, because I didn't select at least one Skill for this person
I can solve this situation with custom Form definition or with override save() method for Person model.
Is it possible to prevent create Person without at least one Skill selected, with set ManyToManyField options? Or I need to create custom logic to handle this situation? Thanks.
I use Django 1.7 and Python 3.4
Update 1. How to create ModelForm to control M2M? Because in cleaned_data I have only fields that I pass for Person form, and haven't data that I pass as M2M fields. I try to create object in Admin Site and control that Skills selected. I enter Skill's via inline.
# admin.py
class PersonSkillsInline(admin.TabularInline):
model = Person.skills.through
extra = 2
class PersonAdmin(admin.ModelAdmin):
inlines = [PersonSkillsInline]
admin.site.register(Person, PersonAdmin)
On a database level... no, that's not possible. Any enforcement of this will have to come from your application logic.
The reason is that every m2m relation has a record with a foreign key to both sides of the m2m relation. SQL cannot enforce the existence of the referencing side of a relationship, only of the referenced side of a relationship.
Furthermore, you can't enforce it in your model either, because the Person has to be created and saved before you can assign any many-to-many relations.
Your only options are to enforce it in the form or the view.
In an InlineModelAdmin this can easily be done by specifying min_num (1.7+):
class PersonSkillsInline(admin.TabularInline):
model = Person.skills.through
min_num = 1
extra = 2

Django form exclude options in select field

I have one model that has a ManyToMany Field (let's call it "Options") with another Model
When I create the ModelForm it displays all options.
Is there any way to exclude some option values or to show only some of them?
Here is an example:
models.py
class Options (model.Models):
name = ...
...
class Anything (model.Models):
...
options = ManyToManyField(Options)
values of "Options" in my DB:
["OK",
"OK_2",
"NOT_OK",
"OK_3,
"NOT_OK_2"]
Let's say that I need to show ONLY the "OK" values and hide or not to show the "NOT_OK" values.
Is there any way to do this with ModelForms?
You certainly can filter the queryset for a foreign key field or m2m on the related model by using a Form or more commonly a ModelForm.
The reason doing this at form level is useful is because that filtering could well be based on business logic which is not applicable in all cases and so allows more flexibility than defining it against the model for example.
While you can do this while defining the form fields it is best to do it once the form has been constructed and so it takes place at runtime and not compile time (I have just experienced a few interesting occasions where this has caused me some issues, however that was an earlier version of Django!)
The following ModelForm would do the job:
class AnythingForm(ModelForm):
options = forms.MultipleChoiceField()
def __init__(self, **kwargs):
super(AnythingForm, self).__init__(self, **kwargs)
self.fields['options'].queryset = Option.objects.filter({pass in your filters here...})
class Meta:
model = Anything
You can pass the limit_choices_to parameter to your ManyToMany field:
from django.db.models import Q
class Anything (models.Model):
options = models.ManyToManyField(Options,
limit_choices_to=Q(name__startswith='OK'))
In django 1.7 you can even pass a callable in case if list of choices should be changed dynamically.

Categories

Resources