django admin onetoone field - django

class Model1(models.Model):
name = models.CharField(...)
...
class Model2(models.Model)
model = models.OneToOneField(Model1)
...
I go to the admin panel. page add an entry to Model2, watch list model. And there all the records from Model1.
Is it possible to customize the admin area so that the list did not get records that already have a relationship.
thank you

You Should override _init_ method of form class.
You can take help from below given code.
from django import forms
from .models import Model2, Model1
class Model2Form(forms.ModelForm):
model1 = forms.ModelChoiceField(queryset=[],)
class Meta:
model = Model1
def __init__(self, *args, **kwargs):
""" initialize form data """
super(Model2Form, self).__init__(*args, **kwargs)
model2_obj = Model2.objects.all().values_list('model1')
model2_list = [data[0] for data in model2_obj]
self.fields['model1'].queryset = Model1.objects.exclude(id__in=model2_list)
In admin.py.
from django.contrib import admin
from .forms import Model2Form
from .models import Model2
class Model2Admin(admin.ModelAdmin):
form = Model2Form
fields = ['model1']
admin.site.register(Model2, Model2Admin)

Related

How to get all the properties of objects using foreign key in django model

Using Djangorestframework I had created rest api. I have two models in my app countries and states. I had related countries model to states model using Foreign key method, But while fetching list of states in States api i am getting states names, but in the place of country i am getting countries primary key id instead of it's name how can i get all the fields of Countries instead of PK id
----------
Models.py code
class countries(models.Model):
country = models.CharField(max_length=10)
def __str__(self):
return self.country
class states(models.Model):
state = models.CharField(max_length=15)
country = models.ForeignKey(countries, on_delete=models.PROTECT)
def __str__(self):
return self.state
----------
Serializers.py code
from rest_framework import serializers
from .models import countries, states
class countiresSerializers(serializers.ModelSerializer):
class Meta:
model = countries
fields = '__all__'
class statesSerializers(serializers.ModelSerializer):
class Meta:
model = states
fields = '__all__'
----------
Viewset.py code--
from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from.models import countries, states
from .serializers import countiresSerializers, statesSerializers
class countryList(APIView):
def get(self, request):
country1 = countries.objects.all()
serializer = countiresSerializers(country1, many=True)
return Response (serializer.data)
def __pos__(self):
pass
class statesList(APIView):
def get(self, request):
state = states.objects.all()
serializer = statesSerializers(state, many=True)
return Response (serializer.data)
def __pos__(self):
pass
I had attached image u can see the country displaying primary id instead of it's name, how can i get name and all other related fields of countries..
You can use depth serializer's option:
class statesSerializers(serializers.ModelSerializer):
class Meta:
model = states
fields = '__all__'
depth = 1

filter on django-import-export

I want to create csv file form my model send a dictionary of Queries ( filter exclude ) to django-import-export and return data from my model.
using flowing code i have all of model fields but i need to filter them with a query.
from import_export import resources
from finance.models import Price
class ExportData(resources.ModelResource):
class Meta:
model = Price
Pass queryset to export method:
queryset = Price.objects.exclude(...)
data = ExportData().export(queryset)
data.csv
To filter only Exported file and not the actual list in the Admin screen you can overwrite the get_export_queryset method
from import_export import resources
from import_export.admin import ImportExportMixin
class ProductAdmin(ImportExportMixin, admin.ModelAdmin):
resource_class = ProductResource
# Override of ImportExportMixin.get_export_queryset
# Filter export to exclude Products where is_active is false
def get_export_queryset(self, request):
return Product.objects.filter(is_active=True)
You can override the export method of resources.ModelResource in your admin.py file, to apply your filter on admin:
from import_export import resources
from finance.models import Price
class ExportData(resources.ModelResource):
class Meta:
model = Price
def export(self, queryset=None, *args, **kwargs):
# For example only export objects with ids in 1, 2, 3 and 4
queryset = queryset and queryset.filter(id__in=[1, 2, 3, 4])
return super(ExportData, self).export(queryset, *args, **kwargs)
You can just modify a export method of ModelResource class.
from import_export import resources
from finance.models import Price
class ExportData(resources.ModelResource):
class Meta:
model = Price
def export(self, queryset = None, *args, **kwargs):
queryset = queryset.exclude(id = 5)
return super().export(queryset, *args, **kwargs)

Django-registration - How to pass the "extra_context" parameter from a subclass Form

I'm using Django Registration(https://bitbucket.org/ubernostrum/django-registration/), and I need to add some fields to the registration of users.
I've made a subclass of the RegistrationForm. My "forms.py" is the following:
from django.contrib.auth.models import User
from myproject.apps.userprofile.models import Gender, UserProfile
from myproject.apps.location.models import Country, City
from django import forms
from registration.forms import RegistrationForm
from registration.models import RegistrationManager
class RegistrationFormExtend(RegistrationForm):
"""
Subclass of ``RegistrationForm`` which adds the fiedls in the userprofile app
"""
gender = forms.ModelChoiceField(queryset=Gender.objects.all(), empty_label="(Nothing)")
country = forms.ModelChoiceField(queryset=Country.objects.all(), empty_label="(Nothing)")
city = forms.ModelChoiceField(queryset=City.objects.all(), empty_label="(Nothing)")
#profile_picture =
To make it work I've changed the "urls.py" to show the "RegistrationFormExtend" form by adding the "form_class" parameter to the "register" view:
from django.conf.urls.defaults import *
from django.views.generic.simple import direct_to_template
from registration.views import activate
from registration.views import register
from myproject.apps.registrationextend.forms import RegistrationFormExtend
urlpatterns = patterns('',
...
url(r'^registar/$',
register,
{'backend': 'registration.backends.default.DefaultBackend', 'form_class': RegistrationFormExtend,},
name='registration_register'),
...
)
After that, I've tested and the form is working. The user is registered successfully, but all the extra fields(gender, country, city) in the "RegistrationFormExtend" are NOT stored in the database.
Reading the documentation, http://docs.b-list.org/django-registration/0.8/views.html#registration.views.register it seems that I must to pass the parameter "extra_context" to the view.
My question is how to pass a dictionary to the "extra_context" parameter. How to refer to the variables "gender", "country" and "city"?
Thanks in advance.
You forgot to have save method in your extended registration form. You have to do something like this:
class RegistrationFormExtend(RegistrationForm):
"""
Subclass of ``RegistrationForm`` which adds the fiedls in the userprofile app
"""
gender = forms.ModelChoiceField(queryset=Gender.objects.all(), empty_label="(Nothing)")
country = forms.ModelChoiceField(queryset=Country.objects.all(), empty_label="(Nothing)")
city = forms.ModelChoiceField(queryset=City.objects.all(), empty_label="(Nothing)")
#profile_picture
def __init__(self, *args, **kw):
super(RegistrationFormExtend, self).__init__(*args, **kw)
def save(self):
#first save the parent form
profile = super(RegistrationFormExtend, self).save()
#then save the custom fields
#i am assuming that the parent form return a profile
profile.gender = self.cleaned_data['gender']
profile.country = self.cleaned_data['country']
profile.city = self.cleaned_data['city']
profile.save()
return profile

Django - Dynamically importing a models form

I want to create a view that is able to show a ModelForm for various different models. It does this by obtaining the content type of the model and then dynamically instantiating the model form associated with that particular model. Here is my model:
from django.db import models
class SomeModel(models.Model):
name = models.CharField(max_length=150)
def __unicode__(self):
return self.name
And inside the same app there is a forms.py with the following form:
from django.forms import ModelForm
from someapp.models import SomeModel
class SomeModelForm(ModelForm):
class Meta:
model = SomeModel
fields = ('name',)
So what I want to do inside of my view file is return the correct form for each model dynamically. I tried the following:
from django.db import models
from someapp.forms import SomeModelForm
class SomeModel(models.Model):
name = models.CharField(max_length=150)
form = SomeModelForm
def __unicode__(self):
return self.name
But it doesn't work because of the obvious circular import. Does anyone have any idea how I might go about achieving this? I tried toying with modelform_factory, but it seems to ignore any of my custom model forms in forms.py.
EDIT: I should of mentioned that I won't have an instance of the model, just the model class itself, so having a method that inside of the model doesn't work (it does, however, work if you are calling it on an instance of the model)
You could get around the circular import by importing your model form inside a method.
class SomeModel(models.Model):
name = models.CharField(max_length=150)
#staticmethod
def get_form_class():
from someapp.forms import SomeModelForm
return SomeModelForm
# in your view:
SomeModel.get_form_class()
Putting the import within a method on the model should be enough to get you around the circular import, so instead of what you have, you'd use:
class SomeModel(models.Model):
...
def get_form(self):
from someapp.forms import SomeModelForm
return SomeModelForm
You can even make it a property if you want with:
form = property(get_form)
There is a built-in func get_model for lazy importing models.
from django.db.models import get_model
SomeModel = get_model('your_app_name', 'SomeModel')
Using __import__ and getattr.
# models.py
class SomeModel(models.Model):
...
#classmethod
def get_form(cls):
try:
app = __import__(cls._meta.app_label)
forms = getattr(app, "forms")
return getattr(forms, "%sForm" % cls.__name__)
except:
return None
# forms.py
class SomeModelForm(forms.Form):
...
in a view you can get the form associate to a models like this:
# views.p
from models import SomeModel
...
def myview(request):
form = SomeModel.getform()

How to fill model field value from a different ModelForm field with some calculation?

I want to have age field in my ModelForm and use it to fill birth_year in the model.
What is the idiomatic way to do this? What method should I provide in my form or model or meta class?
from datetime import datetime
import forms
from myapp.models import MyModel
class MyAgeForm(forms.ModelForm):
age = forms.IntegerField()
# define other custom fields here
class Meta:
model = MyModel
# probably define what fields from the model to include/exclude here
def save(self, *args, **kwargs):
self.instance.birth_year = datetime.now().year - self.cleaned_data['age']
return super(MyAgeForm, self).save(*args, **kwargs)