Search code examples
pythondjangodjango-adminmodels

Trouble Banning users and adding them to table


I Have a function that is intended to ban a user and then add them to the Banned_User table.So that I may then send the user an email with the details of their ban.But I can't seem to get the function to ban and save

Current traceback error: Exception Type: TypeError at /admin/api/profile/ Exception Value: Direct assignment to the forward side of a many-to-many set is prohibited. Use report_reason.set() instead.

def banning_users(self, request, queryset):

for obj in queryset:
    if hasattr(obj, 'user'):
        # This object is a Profile, so lookup the user
        profile = obj
        user = obj.user
    user.is_active = False
    user.save()


    # Get the report(s) for this user
    user_reports = Report.objects.filter(user_reported=profile)

    # Go through each report, in case there are multiples,
    # add a record in the ban table

    banned_reasons = []

    for report in user_reports:
        ban_record = Banned_User.objects.create(profile=profile, report_reason=report)
        ban_record.save() 
        banned_reasons.append(report.get_report_reason_display())



    # Send the email
    subject = 'Ban'
    message = 'You have been banned for the following reasons: []' + \
    report.report_reason + banned_reasons[0] + banned_reasons[1]

    email_from = settings.EMAIL_HOST_USER
    recipient_list = [user.email]
    send_mail( subject, message,email_from, recipient_list)

self.message_user(request, "User is banned and Email has been sent")

BANNED_USER MODEL

class Banned_User(models.Model):
def __str__(self):
    return str.join(str(self.profile), str(self.report_reason.report_reason))
    #return self.profile
    #return str.join(str(self.profile), str(self.report_reason))

profile = models.ForeignKey(
    'Profile',
    on_delete=models.PROTECT,
    blank=False,
    null=False,
    related_name='banned_profile'
)

report_reason = models.ManyToManyField(
    'Report',
    #on_delete=models.PROTECT,
    blank=True,
    #null=True,
)

date_banned = models.DateField(null=True, blank=False,)

REPORT MODEL

class Report(models.Model):
def __str__(self):
    return str.join(str(self.user_reported), str(self.datetime_sent))

TOXICITY = 'Toxicity'
SPORTSMANSHIP = 'Poor sportsmanship'

REPORT_REASON_CHOICES = (
    (TOXICITY, 'Toxicity'),
    (SPORTSMANSHIP, 'Unsportsmanlike Behaviour'),
)

session = models.ForeignKey(
    'Session',
    on_delete=models.PROTECT,
    blank=False,
    null=False,
)

user_reported = models.ForeignKey(
    'Profile',
    on_delete=models.PROTECT,
    blank=False,
    null=False,
    related_name='user_reported_report',
)

sent_by = models.ForeignKey(
    'Profile',
    on_delete=models.PROTECT,
    blank=False,
    null=False,
    related_name='sent_by_report',
)

report_reason = models.CharField(
    max_length=255,
    choices=REPORT_REASON_CHOICES,
    default=TOXICITY,
)

datetime_sent = models.DateTimeField(auto_now_add=True,)

Solution

  • Report reason for failure is you are trying to assing a Foreign Key to many to many field which is set that expects you to use add command.

    ban_record = Banned_User.objects.create(profile=profile, report_reason=report)
    

    which would not work. What you need to do is created the banned_user model for the Profile

    banned_user = profile.banned_profile.create(profile=profile)
    

    then you would add ban reasons to banned user Edited

    reports = banned_user.profile.user_reported_report.all()
    for report in reports:
        banned_user.report_reason.add(report)
    

    You can look at working with many to many fileds here. https://docs.djangoproject.com/en/2.0/topics/db/examples/many_to_many/