Updating a User's skills using ManyToManyField in django - python

I've been stuck on this for a few days (new to django) and can't figure out how to update skills for a specific user model using a ManyToManyField, while simultaneously updating a skill model containing a list of skills. Currently when I enter a value in my SkillForm, it updates the skill model properly and creates a dropdown list of skills for a given CustomUser in the admin. However, I can't figure out how to assign a SPECIFIC skill to a particular user. Any help is appreciated.
models.py:
class Skill(models.Model):
name = models.CharField(max_length =50, null=True, default='')
def __str__(self):
return self.name
class CustomUserManager(UserManager):
pass
class CustomUser(AbstractUser):
objects = CustomUserManager()
skills = models.ManyToManyField(Skill, null=True, blank=True)
position = models.CharField(max_length =50, null=True, default='')
bio = models.CharField(max_length=300, null=True, default='')
admin.py:
class SkillsInline(admin.StackedInline):
model = CustomUser.skills.through
class SkillAdmin(admin.ModelAdmin):
inlines = [SkillsInline ,]
UserAdmin.fieldsets += ('Custom fields set', {'fields': ('position', 'bio', )}),
class CustomUserAdmin(UserAdmin):
model = CustomUser
add_form = CustomUserCreationForm
form = EditProfile
inlines = [SkillsInline ,]
admin.site.register(CustomUser, CustomUserAdmin)
forms.py:
class SkillForm(forms.ModelForm):
name = forms.CharField()
class Meta:
model = Skill
fields =('name' ,)
def clean(self):
cleaned_data = super().clean()
name = cleaned_data.get('name')

I see somes problem here :
class CustomUser(AbstractUser):
objects = CustomUserManager()
skills = models.ManyToManyField(Skill, null=True, blank=True)
position = models.CharField(max_length =50, null=True, default='')
bio = models.CharField(max_length=300, null=True, default='')
When you define an AbstractUser` class, it's mean for Django Authentification purpose, see the doc here., dont do that because it's better to have an unique entry (each user have an unique entry, so you can login each one).
In your system you dont have unique CustomUser, here is a solution IMO:
class User(AbstractUser):
email = models.EmailField(_('email'), unique=True)
class UserAction(models.Model):
objects = CustomUserManager()
user = models.ForeignKey(User, verbose_name="User")
skills = models.ManyToManyField(Skill, null=True, blank=True)
position = models.CharField(max_length =50, null=True, default='')
bio = models.CharField(max_length=300, null=True, default='')
class Skill(models.Model):
name = models.CharField(max_length =50, null=True, default='')
def __str__(self):
return self.name
You now have an unique User, a list of UserAction that have a related Skill
user = User.objects.create(email='my#email.com')
skill = Skill.objects.create(name="shadow step")
user_action = UserAction.objects.create(user=user, skill=skill, position='HERE', bio='10')
Is that what you needed ?

Related

Show secondary foreign key values in the inline django admin

models.py
class FarmerAdvisory(BaseModel):
id = models.AutoField(db_column='id', primary_key=True)
title = models.CharField(db_column='title', max_length=200, null=True, blank=True)
description = models.CharField(db_column='description', max_length=750, null=True, blank=True)
farmer_id = models.ForeignKey(Farmer, on_delete=models.CASCADE, null=True, db_column='farmer_id')
class Meta:
verbose_name = 'Farmer Advisory'
verbose_name_plural = 'Farmer Advisories'
managed = True
db_table = 'farmer_advisory'
class ReplyFarmerAdvisory(BaseModel):
reply = models.CharField(db_column='reply', max_length=750, null=True, blank=True)
label = models.CharField(db_column='label', max_length=100, null=True, blank=True)
farmer_advisory_id = models.ForeignKey(FarmerAdvisory, on_delete=models.CASCADE, db_column='farmer_advisory_id')
objects = models.Manager()
class Meta:
verbose_name = 'Reply Farmer Advisory'
verbose_name_plural = 'Reply Farmer Advisories'
managed = True
db_table = 'reply_farmer_advisory'
class AdvisoryMedia(models.Model):
id = models.AutoField(db_column='id', primary_key=True)
farmer_advisory_id = models.ForeignKey(FarmerAdvisory, on_delete=models.CASCADE,
db_column='farmer_advisory_id',
null=True, blank=True)
reply_farmer_advisory_id = models.ForeignKey(ReplyFarmerAdvisory, on_delete=models.CASCADE,
db_column='reply_farmer_advisory_id', null=True, blank=True)
farmer_media_file = models.CharField(db_column='farmer_media_file', max_length=50, null=True, blank=True)
is_active = models.BooleanField(db_column='is_active', null=False, default=True)
reply_media_file = models.FileField(upload_to=content_file_name, null=True, blank=True,
db_column='reply_media_file')
class Meta:
verbose_name = 'Advisory Media'
verbose_name_plural = 'Advisories Media'
managed = True
db_table = 'advisory_media'
admin.py
class AdvisoryMediaInline(NestedStackedInline):
model = AdvisoryMedia
extra = 0
class ReplyFarmerAdvisoryInline(NestedStackedInline):
model = ReplyFarmerAdvisory
extra = 1
inlines = [AdvisoryMediaInline]
class FarmerAdvisoryAdmin(NestedModelAdmin):
inlines = [ReplyFarmerAdvisoryInline]
I want to show the fields with respect to the farmer advisory. But when i am adding fk_name = 'farmer_advisory_id' inside AdvisoryMediaInline, i am getting error stating
ValueError: fk_name 'farmer_advisory_id' is not a ForeignKey to
'farmer.ReplyFarmerAdvisory'.
But i want to show the farmer advisory related fields which is not coming by itself.
I think what is happening is the model is looking for values with respect to the to foreign key reply advisory media instead of farmer advisory media.
Please let me know if my question is understandable, if yes please guide me through it.

Auto list fields from many-to-many model

I've created a model of analysis types and then I created a table that groups several analyses into one group:
class AnalysisType(models.Model):
a_name = models.CharField(max_length=16,primary_key=True)
a_measur = models.CharField(max_length=16)
a_ref_min = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
a_ref_max = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)
# analysis_group = models.ForeignKey(AnalysysGroup, on_delete=models.CASCADE, default=1)
def __str__(self):
return f"{self.a_name} - {self.a_measur}"
class AnalysysGroup(models.Model):
group_name = models.CharField(max_length=32)
analysis = models.ManyToManyField(AnalysisType, blank=True)
def __str__(self):
return f"{self.group_name}"
I want to have the option to multiply add values via the admin panel (I.E. I chose Analysis type then below appear fields to fill)
class PatientGroupAnalysis(models.Model):
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
analysis_date = models.DateTimeField()
analysis_type = models.ForeignKey(AnalysysGroup, on_delete=models.CASCADE, default=1)
# amalysis_data = ???
def __str__(self):
return f"{self.patient}: {self.analysis_date} - {self.analysis_type} - {self.analysis_data}"
I tried to use analysis_data = analysis.type.objects.all() and etc. but that's the wrong way.
Try this:
Admin panel with StackedInline
from django.contrib import admin
from .models import AnalysisType, PatientGroupAnalysis
# Register your models here.
class PatientGroupAnalysisInline(admin.StackedInline):
model = PatientGroupAnalysis
#admin.register(AnalysisType)
class AnalysisTypeAdmin(admin.ModelAdmin):
list_display = ["id", "a_name", "a_measur", "a_ref_min", "a_ref_max"]
search_fields = ("id", "a_name")
inlines = [PatientGroupAnalysisInline]

I can't create another ForeignKey using Django

I'm working on a small Django Project, I would like to create a second ForeignKey in the same model, but it doesn't work after the migration I don't see the field in my table contact,
this is my Models ( i have a Custom User Model and work fine )
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
username = models.CharField(max_length=255, unique=False, blank=True, null=True)
email = models.EmailField('email address', unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
This is my class Contact ( as you can see I try to add a foreign key called user )
from django.db import models
from list.models import List
from users.models import CustomUser
class Contact(models.Model):
list = models.ForeignKey(List, on_delete=models.DO_NOTHING, related_name="list")
user = models.ForeignKey(CustomUser, on_delete=models.DO_NOTHING, related_name="user")
greeting = models.CharField(null=True, blank=True, max_length=255)
first_name = models.CharField(max_length=60)
last_name = models.CharField(max_length=60)
title = models.CharField(null=True, blank=True, max_length=60)
company = models.CharField(null=True, blank=True,max_length=60)
phone = models.CharField(null=True, blank=True, max_length=60)
def __str__(self):
return self.first_name
What i try to do :
Each user can have Contacts
Each Contact depend on a list
I don't know if this fixes the problem but
you should not name your model field "list"
because "list" is one of python's reserved keywords. When you redefine it Unexpected things can happen

How to display multiple objects from fields in Django Admin

I am a bit stumped as to how I can add multiple access_token and items_ids in Django Admin. The models and apps involved are as follows. This is my first post so please forgive if it isn't in proper format.
Trans/models.py
class Exchange(models.Model):
created = models.DateTimeField()
owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='token', on_delete=models.CASCADE)
access_token = models.CharField(max_length=300, blank=True, default='')
item_id = models.CharField(max_length=300, blank=True, default='')
request_id = models.CharField(max_length=300, blank=True, default='')
class Meta:
ordering = ('item_id',)
I have setup a userprofile section for the admin:
Users/models.py
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True, verbose_name='user', related_name='profile', on_delete=models.CASCADE)
avatar_url = models.CharField(max_length=256, blank=True, null=True)
dob = models.DateField(verbose_name="dob", blank=True, null=True)
public_token = models.CharField(max_length=100, blank=True, null=True, verbose_name='public_token')
access_token = models.CharField(max_length=100, blank=True, null=True, verbose_name='access_token')
item_id = models.CharField(max_length=100, blank=True, null=True, verbose_name='item_ID')
just_signed_up = models.BooleanField(default=True)
def __str__(self):
return force_text(self.user)
class Meta():
db_table = 'user_profile'
users/forms.py
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('user', 'public_token', 'access_token', 'item_id',)
users/admin.py
class UserProfileAdmin(admin.ModelAdmin):
search_fields = ('user', 'dob', 'public_token', 'access_token', 'item_id',)
ordering = ('user',)
list_select_related = ('user',)
admin.site.register(UserProfile, UserProfileAdmin)
class UserProfileAdminInline(admin.TabularInline):
model = UserProfile
I'm really just stumped as I tried making many to many field but couldnt seem to link correctly and or the process broke when testing in a sandbox environment. Any help would be greatly appreciated! In my case I need to record multiple access_tokens and item_ids for each user.
It's a little bit confusing what you are asking...particularly the way that your data model is setup....but I'm going to make a couple of assumptions in my answer (it would be helpful to better understand what you are trying to do at a high level).
I think what you are wanting to do is to be able to configure multiple Exchange objects per user profile...in which case I would set things up this way:
1. The related_name field on the FK to the user profile in the exchange model will be how you access multiple exchanges...so in this case you probably want a pluralized name.
2. To be able to edit multiple in the Django Admin you will need to setup an InlineAdmin object.
3. The CharFields that are actually ON the UserProfile will only ever be single fields...if you want multiple then you need to move them to another related object (like the Exchange model).
4. I don't think what you want here is a ManyToMany as that would imply user's would be sharing these tokens and item ids (or Exchanges?)...but maybe that is what you want...in which case you should change the ForeignKey to UserProfile from the Exchange model to a ManyToManyField. The rest of this post assumes you don't want that.
trans/models.py
from django.db import models
from django.conf import settings
class Exchange(models.Model):
class Meta:
ordering = ('item_id', )
created = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='exchanges', on_delete=models.CASCADE)
access_token = models.CharField(max_length=300, blank=True)
item_id = models.CharField(max_length=300, blank=True)
request_id = models.CharField(max_length=300, blank=True)
users/models.py
from django.db import models
from django.conf import settings
class UserProfile(models.Model):
class Meta:
db_table = 'user_profile'
user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True, verbose_name='user', related_name='profile', on_delete=models.CASCADE)
avatar_url = models.CharField(max_length=256, blank=True)
dob = models.DateField(verbose_name="dob", blank=True, null=True)
public_token = models.CharField(max_length=100, blank=True, null=True)
access_token = models.CharField(max_length=100, blank=True, null=True)
item_id = models.CharField(max_length=100, blank=True, null=True)
just_signed_up = models.BooleanField(default=True)
def __str__(self):
return force_text(self.user)
users/admin.py
from django.contrib import admin
from trans.models import Exchange
from users.models import UserProfile
class ExchangeAdminInline(admin.TabularInline):
model = Exchange
class UserProfileAdmin(admin.ModelAdmin):
inlines = (ExchangeAdminInline, )
search_fields = ('user', 'dob', 'public_token', 'access_token', 'item_id', )
ordering = ('user', )
list_select_related = ('user', )
admin.site.register(UserProfile, UserProfileAdmin)
There is a lot that you can do to configure the inlines to behave how you want...but that's the basics.

Cannot resolve keyword 'article' into field

I know that there are multiple questions about this already but none of them resolves my problem.
I have split my models into multiple files under models folder, viz., models/articles.py, models/core.py etc.
When I try executing
User.objects.annotate(my_count=Count('article'))
django gives me the following error:
FieldError: Cannot resolve keyword 'articles' into field. Choices are: access, cfi_store_item_likes, collaborators, comment, date_joined, documentation, email, emailaddress, first_name, groups, id, images, is_active, is_staff, is_superuser, last_login, last_name, listing, logentry, makey, makey_removed, newproduct, note, password, productdescription, productimage, profile, socialaccount, space_admins, space_members, textdocumentation, tutorial, user_permissions, userflags, username, video
I have the following code in models/abstract.py
class BaseModel(models.Model):
added_time = models.DateTimeField('added time')
is_enabled = models.BooleanField(default=True)
score = models.IntegerField(default=0)
class Meta:
abstract = True
app_label = 'catalog'
I have the following in models/article.py
class Article(BaseModel):
url = models.URLField()
title = models.CharField(max_length=500, null=True, blank=True)
description = models.TextField(null=True, blank=True)
image_url = models.URLField(null=True, blank=True)
rating = models.IntegerField()
recommendation = models.TextField(null=True, blank=True)
user = models.ForeignKey(User, null=True, blank=True)
tags = models.ManyToManyField(ArticleTag, null=True, blank=True)
comments = models.ManyToManyField(Comment, null=True, blank=True)
new_user = models.ForeignKey('NewUser', null=True, blank=True)
class Meta:
app_label = 'catalog'
def __unicode__(self):
return self.title + ' (' + self.url + ')'
I have the following in models/core.py, along with many other models which have been listed as the available options.
class Tutorial(BaseModel):
user = models.ForeignKey(User, null=True, blank=True)
description = models.CharField(max_length=200, null=True, blank=True)
url = models.URLField(max_length=200)
votes = models.IntegerField(default=0)
images = models.ManyToManyField(Image, related_name="tutorialimages",
null=True, blank=True)
class Meta:
app_label = 'catalog'
def __unicode__(self):
return self.url
Why is django not picking up my ForeignKey to User from models from rest of the files? Why is it picking it up only from core.py?
I have posted the models and stacktrace at http://pastebin.com/v6hFdvAC and http://pastebin.com/nxYktwHn.
Because not all users have an article. If you see, your user foreign key in Article Class can be null.
user = models.ForeignKey(User, null=True, blank=True)
then when Django tries to apply the count on null values, it raises an error.
Maybe you can use somehthing like that:
User.objects.objects.filter(article__isnull=False).count()

Categories