Foreign Key problem with django csv import-export package - django

I'm trying to import three datasets for three data models that are interconnected and I cannot seem to properly add in the foreign key. When I try to use the fields.Feild() function to create the foreign key, I get the nameerror in this line: hid = fields.Field(column_name='hid',attribute='hid',..). Please help, I've been trying to upload my datasets for a week. I originally tried to do it manually, but was unable, so now I'm using this package django-import-export.
NameError: name 'fields' is not defined
Here is my models.py
class Service(models.Model):
"""Model representing an author."""
serviceid = models.UUIDField(default=uuid.uuid4, help_text='Unique ID for this particular service in database')
desc_us = models.TextField(blank=True, primary_key = True)
cpt = models.IntegerField(default= 10000)
price = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
_str__(self):
"""String for representing the Model object."""
return self.desc_us
# Create your models here.
class Library(models.Model):
"""Model representing Librarys."""
hid = models.CharField(max_length = 8, null=True)
name = models.CharField(max_length=200, primary_key=True)
hopid = models.UUIDField(default=uuid.uuid4, help_text='Unique ID for this particular library in database')
address = models.CharField(max_length = 200, null = True)
city = models.CharField(max_length = 50, null = True)
state = models.CharField(max_length = 2, null=True)
zipcode = models.CharField(max_length = 5, null=True)
phone = models.CharField(max_length = 12, null=True)
updateDate = models.DateField(blank=True, null=True)
class Meta:
ordering = ['hopid']
def __str__(self):
"""String for representing the Model object."""
return f'{self.name} ({self.address})'
class Price(models.Model):
"""Model with all the hospital prices by service."""
priceid = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this particular service in database')
com_desc = models.CharField(max_length = 200, blank = True, null = True)
service = models.ForeignKey("Service", on_delete=models.SET_NULL, null=True)
price_offer = models.DecimalField(max_digits=8, decimal_places=2, blank=True)
comments = models.CharField(max_length = 200, blank = True, null =True)
hospital = models.ForeignKey("Hospital", on_delete=models.SET_NULL, null=True)
class Meta:
ordering =['service']
def __str__(self):
return f'{self.hospital.name} ({self.service.desc_us}) ({self.price_offer})'
Here is admin.py
from import_export.admin import ImportExportModelAdmin
from import_export import resources
class ServiceResource(resources.ModelResource):
class Meta:
model = Service
report_skipped = True
exclude = ('id','serviceid')
import_id_fields = ('desc_us', 'cpt', 'price',)
#admin.register(Service)
class ServiceAdmin(ImportExportModelAdmin):
resource_class = ServiceResource
class LibraryResource(resources.ModelResource):
class Meta:
model = Library
report_skipped = True
exclude = ('id','hopid','updateDate')
import_id_fields = ('hid', 'name', 'address', 'city', 'state', 'zipcode', 'phone',)
#admin.register(Library)
class LibraryAdmin(ImportExportModelAdmin):
resource_class = LibraryResource
class PriceResource(resources.ModelResource):
hid = fields.Field(column_name='hid',attribute='hid', widget=ForeignKeyWidget(Library, 'name'))
class Meta:
model = Price
report_skipped = True
exclude = ('id','priceid')
#admin.register(Price)
class PriceAdmin(ImportExportModelAdmin):
list_display = ('com_desc', 'cpt', 'price_offer', 'comments', 'hid',)
resource_class = PriceResource

At the top, add:
import import_export
Then change your line of code to:
hid = import_export.fields.Field(column_name='hid',attribute='hid', widget=ForeignKeyWidget(Library, 'name'))
You're currently not telling Django what library to look for 'fields' in, so it doesn't know.

Related

Django serializer data

I need to get value of basket in 'title' not in 'id'.
How can I do this? How can I get a value of 'title' from 'Position' model in another 'Client' model using ManyToManyField. It automatically transmits ID and the 'title' is required
I have tried many ways but... It must be easy, but i search info 2 days
class Position(models.Model):
title = models.CharField(max_length=150, verbose_name='Title')
slug = models.SlugField(max_length=100, unique=True, db_index=True, verbose_name='URL')
description = models.CharField(max_length=500, verbose_name='Describe')
photo = models.ImageField(upload_to="photos/%Y/%m/", verbose_name='Photo', null=True)
price = models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Price')
date_create = models.DateTimeField(auto_now_add=True, verbose_name='Date create')
date_update = models.DateTimeField(auto_now=True, verbose_name='Date update')
is_published = models.BooleanField(default=True, verbose_name='Is published')
in_stock = models.BooleanField(default=True, verbose_name='In stock')
class Client(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
basket = models.ManyToManyField('Position', default=None, blank=True, related_name='basket')
def __str__(self):
return f'{self.user.username}, id-{self.user.id}'
class ClientSerializer(serializers.ModelSerializer):
class Meta:
model = Client
fields = "__all__"
class ClientViewSet(viewsets.ModelViewSet):
serializer_class = ClientSerializer
permission_classes = (IsOwnerOrReadOnly,)
def get_queryset(self):
pk = self.kwargs.get('pk')
# need a list of objects, not an one
return Client.objects.filter(pk=pk)
result:
{
"id": 1,
"user": 1,
"basket": [
1
]
}
need something like this - "basket":['monitor','keyboard']
You can use the PositionSerializer to get the title of each Position object in the Client's basket ManyToManyField.
class PositionSerializer(serializers.ModelSerializer):
class Meta:
model = Position
fields = ('title',)
class ClientSerializer(serializers.ModelSerializer):
basket = PositionSerializer(many=True, read_only=True)
class Meta:
model = Client
fields = "__all__"

Nested relationship returns empty dictionary DRF

I wrote the following code:
class PredictionSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Prediction
fields = ["id", "market"]
depth = 1
class FixtureSerializer(serializers.HyperlinkedModelSerializer):
predictions = PredictionSerializer()
class Meta:
model = Fixture
fields = ["sofascore_id", "home", "away", "league", "round", "date", "predictions"]
depth = 1
class FixtureViewSet(viewsets.ReadOnlyModelViewSet):
"""
API endpoint that allows fixture to be viewed or edited.
"""
serializer_class = FixtureSerializer
permission_classes = [permissions.IsAuthenticated]
filter_backends = [django_filters.rest_framework.DjangoFilterBackend]
filterset_fields = ("home", "away", "sofascore_id", "statistics")
def get_queryset(self):
date = self.request.query_params.get('date')
queryset = Fixture.objects.all().order_by('-date')
if(date):
queryset = Fixture.objects.filter(date__date=date).order_by('date')
return queryset
Corresponding with the following models:
class Market(models.Model):
name = models.CharField(max_length=200)
class Fixture(models.Model):
sofascore_id = models.CharField(max_length=200)
home = models.ForeignKey(Team, on_delete=models.CASCADE, related_name="home")
away = models.ForeignKey(Team, on_delete=models.CASCADE, related_name="away")
league = models.ForeignKey(League, on_delete=models.CASCADE, blank=True)
round = models.CharField(max_length=200, default=None, blank=True, null=True)
date = models.DateTimeField()
statistics = models.ForeignKey(Statistics, on_delete=models.CASCADE, default=None, blank=True, null=True)
updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return u'{0} - {1}'.format(self.home.name, self.away.name)
class Prediction(models.Model):
market = models.ForeignKey(Market, on_delete=models.CASCADE, blank=True)
fixture = models.ForeignKey(to=Fixture, on_delete=models.CASCADE, related_name="predictions", null=True, blank=True)
When I make an request to /fixtures, the 'predictions' dictionary is always empty, but when I run some test code with the following statement:
f = Fixture.objects.get(sofascore_id=match).predictions.all()
I get the the following as return value:
<QuerySet [<Prediction: Prediction object (23)>, <Prediction: Prediction object (24)>, <Prediction: Prediction object (25)>, <Prediction: Prediction object (26)>, <Prediction: Prediction object (27)>, <Prediction: Prediction object (28)>]>
What is the issue here and why am I unable to retrieve my predictions using the written code?
You need to specify the attribute many inside your serializer:
class FixtureSerializer(serializers.HyperlinkedModelSerializer):
predictions = PredictionSerializer(many=True, read_only=True)
class Meta:
model = Fixture
fields = ["sofascore_id", "home", "away", "league", "round", "date", "predictions"]
depth = 1

Django join unmanaged tables

I have a four models which each contains their own data. The models are:
Category (contains department_id foreign key)
Department (contains data, no foreign key)
ProductCategory (join table containing only product_id and category_id)
Product (contains data with no foreign key)
# models.py (excluded the rest for brevity)
from django.db import models
class Department(models.Model):
department_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
description = models.CharField(max_length=1000, blank=True, null=True)
class Meta:
managed = False
db_table = 'department'
class Category(models.Model):
category_id = models.AutoField(primary_key=True)
#department_id = models.IntegerField()
department = models.ForeignKey(Department, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
description = models.CharField(max_length=1000, blank=True, null=True)
class Meta:
managed = False
db_table = 'category'
class Product(models.Model):
product_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
description = models.CharField(max_length=1000)
price = models.DecimalField(max_digits=10, decimal_places=2)
discounted_price = models.DecimalField(max_digits=10, decimal_places=2)
image = models.CharField(max_length=150, blank=True, null=True)
image_2 = models.CharField(max_length=150, blank=True, null=True)
thumbnail = models.CharField(max_length=150, blank=True, null=True)
display = models.SmallIntegerField()
class Meta:
managed = False
db_table = 'product'
class ProductCategory(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
class Meta:
managed = False
db_table = 'product_category'
unique_together = (('product', 'category'),)
From my endpoint, I need to get all products in a department and return the response in the following format:
​"rows"​: [
{
​ "product_id"​: ​integer​,
"name"​: ​string​,
​"description"​: ​string​,
"price"​: ​string​,
​"discounted_price"​: ​string​,
"thumbnail"​: ​string​
}
]
This is the endpoint:
path('products/inDepartment/<int:department_id>/', ProductViewSet.as_view({"get": "get_products_by_department"}))
How can I go about doing this? I'm stuck with the code below:
# products.py
def get_products_by_department(self, request, department_id):
"""
Get a list of Products of Departments
"""
categories = Category.objects.filter(department_id=department_id).values('category_id')
for item in categories:
category_id = item['category_id']
products = ProductCategory.objects.filter(category_id=category_id).values(
'product_id', name=F('product__name'), description=F('product__description'),
price=F('product__price'), discounted_price=F('product__discounted_price'), thumbnail=F('product__thumbnail'))
# Return response
if products.exists():
return Response(products, 200)
else:
return Response(products, 204)
The code above works and gives me the correct response but I'm not sure if I'm doing the query correctly? Should I be using a loop or is there a Django way to do it better without a loop?
Django's ORM allows for reverse relationship lookup.
https://docs.djangoproject.com/en/2.2/topics/db/queries/#lookups-that-span-relationships
categories = Category.objects.filter(department_id=department_id)
products = Product.objects.filter(productcategory__category__in=categories)

Django rest fetch data from bridge model

I want to get all the user details and list of all the roles against the
user details model
My Models
class UserDetail(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,
related_name='userdetail_user', default='111')
cn = models.CharField(max_length=200)
sn = models.CharField(max_length=200)
u_id = models.CharField(max_length=200)
display_name_cn = models.CharField(max_length=200)
display_name_en = models.CharField(max_length=200)
given_name = models.CharField(max_length=200)
employee_number = models.CharField(max_length=200)
email = models.CharField(max_length=200)
created_at = models.DateTimeField(default=datetime.now, blank=True)
last_login = models.DateTimeField(default=datetime.now, blank=True)
def __str__(self):
return self.given_name
class Role(models.Model):
title = models.CharField(max_length=20)
description = models.CharField(max_length=200)
created_at = models.DateTimeField(default=datetime.now, blank=True)
last_updated = models.DateTimeField(default=datetime.now, blank=True)
status = models.BooleanField(default=True)
def __str__(self):
return self.title
class UserRole(models.Model):
userdetail = models.ForeignKey(UserDetail, on_delete=models.CASCADE,
related_name='userrole_userdetail')
role = models.ForeignKey(Role, on_delete=models.CASCADE)
approver = models.ForeignKey(UserDetail, on_delete=models.SET_NULL,
null=True,
related_name='userrole_userdetail_approver')
created_at = models.DateTimeField(default=datetime.now, blank=True)
last_updated = models.DateTimeField(default=datetime.now, blank=True)
status = models.BooleanField(default=True)
My Serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'email')
class UserRoleSerializer(serializers.ModelSerializer):
class Meta:
model = UserRole
fields = (
'id', 'userdetail', 'role', 'approver', 'last_updated', 'status')
depth = 1
def to_representation(self, instance):
representation = super(UserRoleSerializer, self).to_representation(
instance)
representation['userdetail'] = UserDetailSerializer(
instance.userdetail).data
representation['role'] = RoleSerializer(instance.role).data
representation['approver'] = UserDetailSerializer(
instance.approver).data
return representation
class RoleSerializer(serializers.ModelSerializer):
class Meta:
model = Role
fields = ('id', 'title', 'description', 'last_updated', 'status')
class UserDetailSerializer(serializers.ModelSerializer):
user = UserSerializer()
roles = serializers.SerializerMethodField(read_only=True)
class Meta:
model = UserDetail
fields = ('id', 'roles', 'user', 'cn', 'sn', 'u_id', 'display_name_cn',
'display_name_en', 'given_name', 'employee_number', 'email',
'last_login')
lookup_field = 'u_id'
def get_roles(self, obj):
roles = UserRole.objects.filter(userdetail=obj)
return roles
When I try to fetch all the user details it gives me an error
"Object of type 'UserRole' is not JSON serializable".
I have already tried to serialize the list of object fetched inside get_roles method of UserDetailsSerializer but its no help
In your Serializers, you have to replace
roles = serializers.SerializerMethodField(read_only=True)
With
userrole_userdetail = UserRoleSerializer(many=True, read_only=True)
Its because your FK relation name must match the related name given in the model. Also in UserRoleSerializer you do not need the to_representation method.

DRF - nested serializer

I have several models
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
gender = models.CharField(max_length=2)
name = models.CharField(max_length=200)
birthday = models.DateField(auto_now=False, auto_now_add=False)
weight = models.IntegerField(default=0)
heigth = models.IntegerField(default=0)
sign = models.CharField(max_length=200, choices=SIGNS_CHOICES, default='E')
orientation = models.CharField(max_length=200, choices=ORIENTATION_CHOICES, default='E')
bodytype = models.CharField(max_length=200, choices=BODYTYPE_CHOICES, default='E')
education = models.CharField(max_length=200, choices=EDUCATION_CHOICES, default='E')
religion = models.CharField(max_length=200, choices=RELIGION_CHOICES, default='E')
smoking = models.CharField(max_length=200, choices=SMOKING_CHOICES, default='E')
alcohol = models.CharField(max_length=200, choices=ALCOHOL_CHOICES, default='E')
kids = models.CharField(max_length=200, choices=KIDS_CHOICES, default='E')
pets = models.CharField(max_length=200, choices=KIDS_CHOICES, default='E')
location = models.CharField(max_length=100)
latitude = models.FloatField()
longtitude = models.FloatField()
class ProfilePic(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profilePic = models.ImageField(upload_to='Images/', default='Images/None/No-img.jpg')
class ProfileFields(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
order = models.IntegerField(default=0)
and several serizlizers
class ProfilePicSerializer(ModelSerializer):
class Meta:
model = ProfilePic
fields = [
'profilePic',
'user',
]
class ProfileSerializer(ModelSerializer):
class Meta:
model = Profile
fields = '__all__'
class ProfileFieldsSerializer(ModelSerializer):
class Meta:
model = ProfileFields
fields = [
'user',
'title',
'text',
'order'
]
What I try to do is to create user serizlizer that will show profile, profilePic and profileFields
I do it like so
class UserSerializer(ModelSerializer):
profile = ProfileSerializer(many=False)
profilePic = ProfilePicSerializer(many=False)
profile_fields = ProfileFieldsSerializer(many=True)
class Meta:
model = User
fields = '__all__'
write_only_fields = ('password',)
read_only_fields = ('id',)
def create(self, validated_data):
user = User.objects.create(
username=validated_data['username'],
email=validated_data['email'],
)
user.set_password(validated_data['password'])
user.save()
return user
But I get error
Got AttributeError when attempting to get a value for field `profilePic` on serializer `UserSerializer`.The serializer field might be named incorrectly and not match any attribute or key on the `User` instance.Original exception text was: 'User' object has no attribute 'profilePic'.
Profile model adds to JSON, but profilePic and profileFields return error about not matching and attribute. What Am I doing wrong here ?
It is not recognizing profilePic on the user instance because it doesn't exist. If you try to do user.profilePic you'll get the same error.
You should be able to set the related_name on the ProfilePic model user ForeignKey so that user has a profilePic property and user.profilePic returns the user's profile pic.
class ProfilePic(models.Model):
user = models.OneToOneField(User, related_name="profilePic", on_delete=models.CASCADE)
...