How to assign subject name to their proper field - django

I have used django-import-export package. And want to have related database from csv file of format,
roll_no,student_name,subject_1_mark,subject_2_mark,....subject_n_mark
i'm having difficulty of assigning subject mark to their appropriate field on django ORM
example:
#csv file
roll_no, student_name, FOCP, IT, OS, DS, DL
201,john,56,34,65,34,68
Models.py
class Student(models.Model):
""" Store Student Information """
student_name = models.CharField(max_length=255)
roll_no = models.IntegerField()
class Subject(models.Model):
""" Store Subject Information """
subject_name = models.CharField(max_length=150, null=True, blank=True)
sub_code = models.CharField(max_length=255, unique=True, null=True,blank=True)
class Exam(models.Model):
""" Store Exam Information """
exam_type = models.CharField(max_length=150, null=True, blank=True)
exam_date = models.DateField(null=True, blank=True)
class Mark(models.Model):
""" Store Mark Information """
subject_name = models.ForeignKey(Subject, related_name='marks', null=True, blank=True)
exam = models.ForeignKey(Exam, related_name='marks', null=True, blank=True)
mark = models.IntegerField(null=True, blank=True)
settings.py
INSTALLED_APPS = (
...
'import_export',
)
admin.py
from django.contrib import admin
from import_export.admin import ImportExportModelAdmin
from import_export import resources
from .models import Subject
class SubjectResource(resources.ModelResource):
class Meta:
model = Subject
class SubjectAdmin(ImportExportModelAdmin, admin.ModelAdmin):
resource_class = SubjectResource
admin.site.register(Subject, SubjectAdmin)

Use Fields for mapping
Field represent mapping between object field and representation of this field.

I override before_import and did some additional logic on data that solve my problem. I had opened issue on github https://github.com/django-import-export/django-import-export/issues/644#issuecomment-320966810

Related

Recording user activity in django?

I have a project in which some user can perform CRUD activities. I want to record who did what and when. Currently, I am thinking of making a model
class UserAction(models.Model):
user_id = models.CharField(max_length=100)
action_flag = models.CharField(max_length=100)
class_id = models.CharField(max_length=100)
action_taken_at = models.DateTimeField(default=datetime.now())
and making a function that fills my UserAction table. Is there any better way to do this?
app/models.py:
from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
class Action(models.Model):
sender = models.ForeignKey(User,related_name='user',on_delete=models.CASCADE)
verb = models.CharField(max_length=255)
target_ct = models.ForeignKey(ContentType, blank=True, null=True,
related_name='target_obj', on_delete=models.CASCADE)
target_id = models.PositiveIntegerField(null=True, blank=True)
target = GenericForeignKey('target_ct', 'target_id')
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-created',)
def __str__(self):
return self.pk
app/admin.py
from .models import Action
admin.site.register(Action)
How you can use it ?
you can now import this models(Action) inside any of yours views.py.
Example if you have a post and a user likes it.you can just write
Action.objects.create(sender=request.user,verb="likes this post",target=post)
and now when you look at your admin you will see that tartget_id=post.pk
Here I assume that a user is authenticated and you can change it for your own.Happy coding!!!
You can do it by creating a model in
Models.py
class Auditable(models.Model):
ip = models.GenericIPAddressField(null=True)
user_agent = models.CharField(max_length=255, blank=True)
remote_host = models.CharField(max_length=255, blank=True)
created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name="%(app_label)s_%(class)s_created_by", null=True, blank=True) # this is for web user
modified_at = models.DateTimeField(auto_now=True, blank=True, null=True)
modified_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name="%(app_label)s_%(class)s_modified_by", null=True, blank=True) # this is for web user
class Meta:
abstract = True
def get_fields(self):
list_fields = ['ip', 'user_agent',
'remote_host', 'created_by', 'modified_by']
return [(field.verbose_name, field._get_val_from_obj(self)) for field in self.__class__._meta.fields if field.name not in list_fields and not
(field.get_internal_type() == "DateTimeField" and
(field.auto_now is True or field.auto_now_add is True)) and
field.concrete and (not field.is_relation or field.one_to_one or
(field.many_to_one and field.related_model))]
You can give any class name (i have given auditable). So all you have to do is pass this class (auditable) in your every model instead of models.Model
For Eg:
class Student(Auditable):
By doing this it will add all the auditable fields records in every table you have created.
Hope you may get your answer by doing this.

Get All Changes of Any registered model of a single user django-simple-history

# settings.py
INSTALLED_APPS = [
# ...
'simple_history',
# ...
]
MIDDLEWARE = [
# ...
'simple_history.middleware.HistoryRequestMiddleware',
# ...
]
Models:
from django.db import models
from apps.companies.models import Company
from simple_history.models import HistoricalRecords
# Create your models here.
class User(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=20)
history = HistoricalRecords()
class Contact(TimeStamp):
name = models.CharField(max_length=100, verbose_name='Person Name')
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
phone_number = models.CharField(max_length=100, verbose_name='Personal Number', null=True, blank=True)
email = models.EmailField(null=True, blank=True, verbose_name='Personal Email')
designation = models.CharField(max_length=100)
history = HistoricalRecords()
def __str__(self):
return self.name
user = User.objects.first()
is there anyway to get all changes any model by the user
Your question seems similar than this issue on the django-simple-history repository : https://github.com/jazzband/django-simple-history/issues/684
You'd have to query each historical model since they're all in
separate tables. You could build a way to automatically detect which
models are historical and get them though.

Django import-export display manytomany as a name instead of ids when exporting to csv

How do I display a manytomany column as a list of names instead of ids using Django import-export?
Currently my models and resources.py looks like this and returns a csv with a list of ids for the country column:
models.py
class Country(models.Model):
name = models.CharField(max_length=50, null=False,
blank=False, unique=True)
def __str__(self):
return self.name
class Species(models.Model):
name = models.CharField(max_length=50, null=False, blank=False)
country = models.ManyToManyField(Country)
def __str__(self):
return self.name
resources.py
from import_export import resources,fields
from import_export.widgets import ManyToManyWidget
from .models import Species, Country
class SpeciesResource(resources.ModelResource):
country=fields.Field(attribute='country', widget=ManyToManyWidget(Country), column_name='Country')
name = fields.Field(attribute='name', column_name='Name')
class Meta:
model = Species
fields =('name','country')
export_order = fields
Just add field you need in widget:
widget=ManyToManyWidget(Country, field='name')

Not getting foreign key data in django api views

Currently I have a site, and I want the user to be able to view their liked articles. I want this to be included in the user api view that is already set up. I have tried the tracks = serializers.StringRelatedField(many=True)that is in the drf docs yet this didn't work. I have also tried the following:
from rest_framework import serializers
from articles.models import Article, CustomUser,FavoriteArticles
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('title', 'content')
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = CustomUser
fields = '__all__'
class FavoriteArticleSerializer(serializers.ModelSerializer):
class Meta:
model = FavoriteArticles
fields = '__all__'
class UserProfileSerializer(serializers.ModelSerializer):
fav_title = FavoriteArticleSerializer(read_only=False)
class Meta:
model = CustomUser
fields = 'username, git, email, fav_article, fav_title, homepage'
and my models:
from django.db import models
# users/models.py
from django.contrib.auth.models import AbstractUser
from django.db.models.signals import post_save
from django.dispatch import receiver
import uuid
class ProgrammingLanguage(models.Model):
programming_language = models.CharField(max_length=120, null=False, primary_key=True, default="React")
def __str__(self):
return self.programming_language
class Article(models.Model):
title = models.CharField(max_length=25, primary_key=True)
content = models.TextField()
usedfor = models.TextField()
url=models.CharField(max_length=200, null=True)
article_programming_language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE, related_name="article_programming_language", default="react")
score = models.IntegerField(max_length=5, null=0)
def __str__(self):
return self.title
class CustomUser(AbstractUser):
username = models.CharField(max_length=50, unique=True, primary_key=True)
git = models.CharField(max_length=200, null=True)
homepage = models.CharField(max_length=250, null=True)
user_programming_language = models.ForeignKey(ProgrammingLanguage, on_delete=models.CASCADE, related_name="most_used_programming_language", default="react")
def __str__(self):
return str(self.username)
class FavoriteArticles(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
fav_title = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='fav_title')
reasons_liked = models.CharField(max_length=120, null=True)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, related_name="user", default="tom" )
def __unicode__(self):
return '%s: %s' % (self.fav_title, self.reasons_liked)
I think you misunderstood what related_name means. It specifies how you would access a model from its reverse relationship. So I'd recommend you remove it from fields in your FavoriteArticles model and use the default Django already provides (in this case favoritearticles_set):
class FavoriteArticles(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
fav_title = models.ForeignKey(Article, on_delete=models.CASCADE)
reasons_liked = models.CharField(max_length=120, null=True)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, default="tom")
def __unicode__(self):
return '%s: %s' % (self.fav_title, self.reasons_liked)
This way, you can access favorite articles of a user via my_user.favoritearticles_set.all(). Then, you can change your UserSerializer to include a liked_articles field which is populated from the favoritearticles_set reverse relationship to a user's FavoriteArticles using a source attribute:
class UserSerializer(serializers.ModelSerializer):
liked_articles = FavoriteArticleSerializer(source='favoritearticles_set', many=True, read_only=True)
class Meta:
model = CustomUser
# explicitly include other fields as required
fields = ('username', 'git', 'user_programming_language', 'liked_articles')
Note that we've made this a read_only field, so it will only get populated if you perform a GET request.

Show columns of referenced table instead of the object in django admin

How can I show the columns id, title and the year of the book instead of "Books object"?
This screenshot shows the current state:
My model.py looks like this:
from __future__ import unicode_literals
from django.db import models
class Authors(models.Model):
name = models.CharField(max_length=45, blank=True, null=True)
birthday = models.DateField(blank=True, null=True)
class Meta:
managed = True
db_table = 'authors'
class AuthorsBooks(models.Model):
author_id = models.OneToOneField('Authors', models.DO_NOTHING, db_column='author_id', primary_key=True)
book_id = models.OneToOneField('Books', models.DO_NOTHING, db_column='book_id', primary_key=True)
class Meta:
managed = True
db_table = 'authors_books'
unique_together = (('author_id', 'book_id'),)
class Awards(models.Model):
author = models.OneToOneField('Authors', models.DO_NOTHING, db_column='author', primary_key=True)
award_name = models.CharField(max_length=45)
year = models.IntegerField(blank=True, null=True)
class Meta:
managed = True
db_table = 'awards'
unique_together = (('author', 'award_name'),)
class Books(models.Model):
titel = models.CharField(max_length=45, blank=True, null=True)
year = models.IntegerField(blank=True, null=True)
class Meta:
managed = True
db_table = 'books'
In the class AuthorsBooks I have changed the two foreign keys to OneToOneFields.
My admin.py looks like this:
from django.contrib import admin
from myapp.models import Authors
...
class AwardsInline(admin.TabularInline):
model = Awards
class AuthorsBooksInline(admin.TabularInline):
model = AuthorsBooks
class AuthorsAdmin(admin.ModelAdmin):
list_display = ("name", "birthday" )
inlines = (AwardsInline, AuthorsBooksInline)
admin.site.register(Authors, AuthorsAdmin)
In your models.py file, you can use the special __str__ method in your concerned class to make your objects more descriptive. (This is generally the way most programmers do it)
def __str__(self):
return self.title #if your using 'title' as the attribute to identify your objects
You can choose any other attribute to make your object descriptive.
Good luck!
Add a unicode function in your models.py per model.
class Authors(models.Model):
name = models.CharField(max_length=45, blank=True, null=True)
birthday = models.DateField(blank=True, null=True)
class Meta:
managed = True
db_table = 'authors'
def __unicode__(self):
return self.name
Unicode didnt work for me, but overriding str worked