I have 2 different application in python. I want to import model and use it to make serializer function in another app. Here is my code:
from django.contrib.auth import models as auth_models
from . import models as client_models
from crm.models import models as crm_models
from rest_framework import serializers
class Capability(serializers.ModelSerializer):
class Meta:
model = crm_models.Capability
fields = ["id", "name"]
class Client(serializers.ModelSerializer):
industry = Industry(read_only=True)
capability = Capability(read_only=True)
class Meta:
model = client_models.Client
fields = [
"id",
"company",
"entity",
"account_status",
"capability"]
Here I am getting error for,
in Meta
model = crm_models.Capability
AttributeError: module 'django.db.models' has no attribute 'Capability'
Without seeing the file structure I'd take a guess that you want to change your import to:
from crm import models as crm_models
as I think you are looking for models in models currently.
Try to use this :-
from crm.models import Capability
class Capability(serializers.ModelSerializer):
class Meta:
model = Capability
fields = ["id", "name"]
Related
Is there a way how to dynamically generate a Django rest framework serializers?
Considering this:
class BlogSerializer(serializers.ModelSerializer):
class Meta:
model = models.Blog
fields = get_all_model_fields(models.Blog)
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = models.Post
fields = get_all_model_fields(models.Post)
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = models.User
fields = get_all_model_fields(models.User)
I am wondering if something like following example could be possible:
from django.apps import apps
models = [model for model in apps.get_models()]
for model in models:
type(model.__name__+'Serializer',(serializers.ModelSerializer,),{
type("Meta",(),{
"model":model,
"fields": get_all_model_fields(model)
})
})
Or is there any other way how to generate DRF serializers?
Here's a function to build a ModelSerializer for a given Model (tested with Django 3.2, DRF 3.12.4 and Python 3.8):
from functools import lru_cache
from typing import Type
from django.db import models
from rest_framework import serializers
#lru_cache(maxsize=0)
def model_serializer(model: Type[models.Model]) -> Type[serializers.ModelSerializer]:
meta_class = types.new_class("Meta")
setattr(meta_class, "model", model)
setattr(meta_class, "fields", "__all__")
result = types.new_class(
model.__name__ + "Serializer", (serializers.ModelSerializer,), {}
)
setattr(result, "Meta", meta_class)
return result
If you are certain that you will call this function only once for each serializer, you can omit the #lru_cache to preserve some memory.
Example usage:
class MyModel(models.Model):
some = models.CharField(max_length=123)
other = models.IntegerField()
MyModelSerializer = model_serializer(MyModel)
my_serializer = MyModelSerializer({"some": "abc", "other": 1234})
my_serializer.is_valid(True)
To add the serializers for all your models to the current module's namespace:
from django.apps import apps
for model in apps.get_models():
serializer_type = model_serializer(model)
globals()[serializer_type.__name__] = serializer_type
Your approach will work - but for Django to find about these serializers you have to assign them to the module namespace.
In your code, you just call type - the serializer class is created and "thrown away" immediately. Even if the base Django class serializers.ModelSerializer keep a reference to it in a registry, you would not be able to import your serializers and make use of them.
All you have to do is to add them to the dictionary returned by globals(). Likewise, the namespace you create for the class also has to be a dictionary -since you are calling "type" but not actually assigning its name as "Meta", you create a set, not a dictionary, and your call to type will fail as it was expecting a dictionary.
So, I did not check if the code actually will work, but the idea, based on yours is:
from django.apps import apps
models = [model for model in apps.get_models()]
for model in models:
name = f"{model.__name__}Serializer"
globals()[name] = type(name,(serializers.ModelSerializer,),{
"Meta": type("Meta",(),{
"model":model,
"fields": get_all_model_fields(model)
})
})
del models, model, name
I got the following error during creation of django serializer.
ImportError: cannot import name 'fields' from 'django.db.models.fields' (/home/user_name/anaconda3/lib/python3.7/site-packages/django/db/models/fields/__init__.py)
and the serializer.py file is
from django.db.models.base import Model
from django.db.models.fields import fields, files
from rest_framework import serializers
from .models import Lead
#create serializers for Lead
class LeadSerializer(serializers.ModelSerializer):
class Meta:
model = Lead
fields = '__all__'
my current django version is 3.0.7.
what is wrong in this code ?
I'm not sure why you are trying to import fields or files as a matter of fact.
You are trying to import fields from fields. That will not work.
Also, the class Meta doesn't need you to import fields as it has access to this already. Remove the second line of code and give it a go, or if you need files for some other part of your code then just remove fields.
I am using Django 2.2 and have two applications authentication and multi_users
There is UserSerializer in authentication application. The multi_users model has a field shared_user and thus using UserSerializer in the multi_users.serializers to serialize the shared_user field.
Now, there is AccessLevelPermissionSerializer class in the multi_users.serializers which I need in the authentication.serializers to serializer permissions of the user.
This is giving error as
ImportError: cannot import name 'AccessLevelPermissionSerializer' from 'multi_users.serializers' (/app/multi_users/serializers.py)
authentication.serializers
from authentication.models import Profile, User, Preference
class UserBaseSerializer(UserDetailsSerializer):
class Meta(UserDetailsSerializer.Meta):
fields = ('email', 'first_name', 'last_name')
class UserSerializer(UserBaseSerializer):
from multi_users.serializers import AccessLevelPermissionSerializer
permissions = AccessLevelPermissionSerializer(required=False)
class Meta(UserDetailsSerializer.Meta):
fields = UserBaseSerializer.Meta.fields + (
'permissions'
)
multi_users.serializers
from authentication.serializers import UserBaseSerializer
class SharedPermissionSerializer(serializers.ModelSerializer):
class Meta:
model = SharedPermission
fields = [
'code',
'name',
]
class AccessLevelPermissionBaseSerializer(serializers.ModelSerializer):
permission = SharedPermissionSerializer(required=False)
class Meta:
model = AccessLevelPermission
fields = [
'value',
'permission'
]
# Import this in the `authentication.serializers`
class AccessLevelPermissionSerializer(AccessLevelPermissionBaseSerializer):
pass
class MultiUserSerializer(serializers.ModelSerializer):
shared_user = UserBaseSerializer(required=False) # Use from `authentication.serializers`
class Meta:
model = MultiUser
depth = 1
fields = [
'id',
'shared_user',
'access_level',
]
How to resolve this circular import issue?
Hi may be this will help , try to remove from authentication.serializers import UserBaseSerializer from multi_users.serializers because when you try to access
from multi_users.serializers import AccessLevelPermissionSerializer
permissions = AccessLevelPermissionSerializer(required=False)
this code from authentication.serializers, you being in authentication.serializers try to access from multi_users.serializers import AccessLevelPermissionSerializer
which will redirect your call to multi_users.serializers where you are again importing from authentication.serializers import UserBaseSerializer which making it circular being in that file you again access another file which indirectly calling same file so please try to remove from authentication.serializers import UserBaseSerializer from multi_users.serializers
This is my forms.py file!!!
from django import forms
from . models import URLModel
class URLForm(forms.ModelForm):
class Meta:
model = 'URLModel'
fields = ['url']
This is my models.py file
from django.db import models
# Create your models here.
class URLModel(models.Model):
url=models.URLField(unique=True)
short=models.CharField(max_length=200,unique=True)
def __str__(self):
return self.url
Now i just wanted to ask that why this error is coming and i have revieved and i cant observe any error for real...please help
# Remove single quote from your model specification in forms.py
from django import forms
from .models import URLModel
class URLForm(forms.ModelForm):
class Meta:
model = URLModel
fields = ('url',)
This is my first time using Django and I am completely stuck at how to use ModelForms in my project. I have been able to follow the online tutorials this far but without ModelForms(to add data into a Postgresql database), I can't proceed onward. I am trying to simply make a form page that lets the users add a few inputs (2 datefields and 1 textfield) and by submitting that form, the data will be added to the database.
The error I have been getting is:
AttributeError: 'Hyuga_Requests' object has no attribute 'name' [where Hyuga_Request is a class set in the models.py]
models.py
from __future__ import unicode_literals
from django.db import models
from django.forms import ModelForm
class Hyuga_Requests(models.Model):
name = models.CharField(max_length=50)
s_date = models.DateField(auto_now=True)
e_date = models.DateField(auto_now=True)
reason = models.TextField(max_length=500)
def __unicode__(self):
return self.name
views.py
from django.shortcuts import render
from django import forms
from .forms import Hyuga_RequestForm
def create_req(request):
form = Hyuga_RequestForm()
context = {"form":form,}
return render(request,"request_form/requestform.html", context)
forms.py
from django import forms
from .models import Hyuga_Requests
from django.forms import ModelForm
class Hyuga_RequestForm(forms.ModelForm):
class Meta:
model = Hyuga_Requests()
fields = ['name','s_date','e_date','reason']
Please help this noobie...
Don't instantiate the model in the class Meta inside the Hyuga_RequestForm class.
model = Hyuga_Requests() should be model = Hyuga_Requests
model = Hyuga_Requests() -> model = Hyuga_Requests
The error come because you are calling the model on the form.
from django import forms
from .models import Hyuga_Requests
from django.forms import ModelForm
class Hyuga_RequestForm(forms.ModelForm):
class Meta:
model = Hyuga_Requests
fields = ['name','s_date','e_date','reason']
Note: i suggest to you use on the any class you define on python not use "_", you can check more about PEP8 and code styles here: https://www.python.org/dev/peps/pep-0008/