0

I have a simple banning function that sets user active to false and a basic emailing function to send emails. The tables I am working with are User,Profile,Report & Banned_User Table.

I am looking to:

  1. add the user Profile,Reason_reported from Report table and datetime that they were banned into the Banned_User table once banned.
  2. send these details to the users email

Currently I am recieving a 'Attribute Error at /admin/api/profile/: WSGIRequest' object has no attribute 'report'' and not sure how to go about doing these 2 things.

def banning_users(self, request, queryset):

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

    #email function
    banned_user = Banned_User.objects.create(profile=request.user.profile, report_reasons=request.report.report_reason)
    banned_user.save()
    #Sends ban email to user,does not send through the variables yet
    subject = 'Ban'
    message =   'You have been banned'
    email_from = settings.EMAIL_HOST_USER
    recipient_list = [obj.email]
    send_mail( subject, message,email_from, recipient_list )
    obj.save()


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

Tables are below:

Report Table

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,)

Banned User Table

class Banned_User(models.Model):
def __str__(self):
    return self.user.get_username

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

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

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

PROFILE:

class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.PROTECT)

def __str__(self):
    return self.user.username

USWEST = 'US-West'
USEAST = 'US-East'
EUROPE = 'Europe'
OCEANIA = 'Oceania'
ASIA = 'Asia'
SOUTHAMERICA = 'South America'
SOUTHAFRICA = 'South Africa'
MIDDLEEAST = 'Middle-East'

PREF_SERVER_CHOICES = (
    (USWEST, 'US-West'),
    (USEAST, 'US-East'),
    (EUROPE, 'Europe'),
    (OCEANIA, 'Oceania'),
    (ASIA, 'Asia'),
    (SOUTHAMERICA, 'South America'),
    (SOUTHAFRICA, 'South Africa'),
    (MIDDLEEAST, 'Middle-East'),
)

pref_server = models.CharField(
    max_length=20,
    choices=PREF_SERVER_CHOICES,
    default=USWEST,
)

TEAMWORK = 'Teamwork'
COMMUNICATION = 'Communication'
SKILL = 'Skill'
SPORTSMANSHIP = 'Sportsmanship'

COMMENDS_CHOICES = (
    (TEAMWORK, 'Teamwork'),
    (COMMUNICATION, 'Communication'),
    (SKILL, 'Skill'),
    (SPORTSMANSHIP, 'Sportsmanship'),
)
teamwork_commends = models.IntegerField(null=False, blank=False, default='0',)
communication_commends = models.IntegerField(null=False, blank=False, default='0',)
skill_commends = models.IntegerField(null=False, blank=False, default='0',)
sportsmanship_commends = models.IntegerField(null=False, blank=False, default='0',)

# Weighting of commends
commend_priority_1 = models.CharField(null=False, blank=False, max_length=20, default=TEAMWORK, choices=COMMENDS_CHOICES,)
commend_priority_2 = models.CharField(null=False, blank=False, max_length=20, default=COMMUNICATION, choices=COMMENDS_CHOICES,)
commend_priority_3 = models.CharField(null=False, blank=False, max_length=20, default=SKILL, choices=COMMENDS_CHOICES,)
commend_priority_4 = models.CharField(null=False, blank=False, max_length=20, default=SPORTSMANSHIP, choices=COMMENDS_CHOICES,)

# Other details
birth_date = models.DateField(null=True, blank=False,)
sessions_played = models.IntegerField(null=False, blank=False, default=0,)
received_ratings = models.IntegerField(null=False, blank=False, default=0,)
in_queue = models.BooleanField(null=False, blank=False, default=False,)

# The users id on discord, which will never change. Current max length is 19, but set to 20 for safe measure (64bit Integer)
discord_id = models.CharField(max_length=20, null=True, blank=True,)

TRACEBACK:

AttributeError at /admin/api/profile/

'WSGIRequest' object has no attribute 'report'

Request Method:     POST
Request URL:    http://127.0.0.1/admin/api/profile/
Django Version:     2.0.5
Exception Type:     AttributeError
Exception Value:    

'WSGIRequest' object has no attribute 'report'

Exception Location:     /home/mihir/Capstone-Project/siteroot/apps/api/admin.py in banning_users, line 31
Python Executable:  /usr/bin/python3.6
Python Version:     3.6.5
Python Path:    

['/home/mihir/Capstone-Project/siteroot',
 '/usr/lib/python36.zip',
 '/usr/lib/python3.6',
 '/usr/lib/python3.6/lib-dynload',
 '/usr/local/lib/python3.6/dist-packages',
 '/usr/lib/python3/dist-packages',
 '/var/www/CapstoneProject/siteroot',
 '/var/www/CapstoneProject/siteroot/mysite']

Server time:    Thu, 10 May 2018 03:36:51 +0000

new code:

    def banning_users(self, request, queryset):

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

        banned_user = Banned_User.objects.create(profile=request.user.profile)
        banned_user.report_reason.add(request.user.profile.user_reported_report.all())
        banned_user.save()
        #Sends ban email to user,does not send through the variables yet
        subject = 'Ban'
        message =   'You have been banned for being trash'
        email_from = settings.EMAIL_HOST_USER
        recipient_list = [obj.email]
        send_mail( subject, message,email_from, recipient_list )
        obj.save()
Anuj
  • 994
  • 11
  • 21
Shadowwz
  • 57
  • 1
  • 7

3 Answers3

2

I am looking to:

  1. add the user Profile,Reason_reported from Report table and datetime that they were banned into the Banned_User table once banned.

  2. send these details to the users email

Cutting down your question into the actual problem, the steps are first to create the ban report, then add the user and finally send the email.

The error message is telling you there is no report attribute for the request object, which makes sense since the report it tied to the user, not the request.

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

        # 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.create(profile=profile, report_reason=report, date_banned=datetime.datetime.today())
            banned_reasons.append(report.get_report_reason_display())

        # Send the email
        subject = 'Ban'
        message = 'You have been banned for the following reasons: {}'
        message.format(','.join(banned_reasons))
        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")
Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
  • There is no `user_profile` in Report Model,Did you mean change it to `User_reported`? – Shadowwz May 10 '18 at 05:57
  • uh,I'm getting an interesting error of `AttributeError at /admin/api/profile/ type object 'Banned_User' has no attribute 'create'` when banning, how is this even possible? – Shadowwz May 10 '18 at 06:16
  • 1
    Got it to work by changing to Banned_User.objects.create,FUnction now sends email!! Issue is that email only shows "You have been banned for the following reasons: {}" with no actual reasons written. – Shadowwz May 10 '18 at 06:22
1

The issue comes from this line:

banned_user = Banned_User.objects.create(profile=request.user.profile, 
           report_reasons=request.report.report_reason)

You're trying to access report inside request, whereas request doesn't have have this attribute.

I suggest that you change your ForeignKey to ManyToManyField, since a user can have multiple reports.

class Banned_User(models.Model):
    def __str__(self):
        return self.user.get_username

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

    report_reasons = models.ManyToManyField('Report',blank=True)

So you would have this:

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

# email function
banned_user = Banned_User.objects.create(profile=request.user.profile)
banned_user.report_reasons.add(request.user.profile.user_reported_report.all())
# rest of code 
Lemayzeur
  • 8,297
  • 3
  • 23
  • 50
  • It returns with a `ValueError at /admin/api/profile/ Cannot assign ".RelatedManager object at 0x7ffaa6e35550>": "Banned_User.report_reason" must be a "Report" instance.` ERROR. – Shadowwz May 10 '18 at 04:28
  • I have added my profile model if it may help to see the relations,I did not add it before as to not make the question too lengthy – Shadowwz May 10 '18 at 04:28
  • Yeah, before you edited, I had updated my answer, because it's obvious that `Profile` has `OneToOne` to User like I see in many django projects. check my answer – Lemayzeur May 10 '18 at 04:34
  • I had checked your updated comment and retried the code before editing my comment :). The error in my comment is from the updated code – Shadowwz May 10 '18 at 04:37
  • oh sorry, this is a RelatedManaget, so you access it with `all()`, and select what you want, for instance, the first one: updated my answer – Lemayzeur May 10 '18 at 04:40
  • `request.user.profile.user_reported_report.all().first()`, Note I select the first one, Actually, the user can have more than one Report, so how will you select the wanted report? – Lemayzeur May 10 '18 at 04:42
  • Ah right i get what you're saying.Essentially if they have 2 different reports for 2 different reasons, I am trying to send them an email with a joined string of both the reasons they've been reported for.So I would be trying to save both the reasons from both(or all) reports into `Banned_User` model – Shadowwz May 10 '18 at 04:46
  • Got it, so this is what you have to do, check my updated code – Lemayzeur May 10 '18 at 04:58
  • Its currently returning a `TypeError at /admin/api/profile/ int() argument must be a string, a bytes-like object or a number, not 'QuerySet'` ERROR – Shadowwz May 10 '18 at 05:08
  • did you try my method? where exactly you think you got this error? can you update your code with that – Lemayzeur May 10 '18 at 05:11
  • Yeah I have tried your method.If I follow the code from before as `banned_user = Banned_User.objects.create(profile=request.user.profile, report_reason=request.user.profile.user_reported_report.all().first()) banned_user.save()` It functions as normal.But trying to add with the current code in your comment gives out a type error – Shadowwz May 10 '18 at 05:17
  • This method would work with only one report, Note that my answer is all about adding multiple reports to Banned_User instance. so `ForeignKey` becomes `ManyToManyField` model has changed – Lemayzeur May 10 '18 at 05:20
  • Yeah I have changed the model to a ManyToMany field,I realised thanks to you that my model was flawed.:) The code I have right now is the same as the code you have posted above – Shadowwz May 10 '18 at 05:23
  • Still can't seem to get rid of the error though.I might have to add one report only If I can't fix it – Shadowwz May 10 '18 at 05:40
  • Post your new code, so I can see what you've done, and help you – Lemayzeur May 10 '18 at 05:41
0

This is the code that finally got it working :) thanks everyone for the help

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()

        banned_reasons = []

    
        banned_user = profile.banned_profile.create(profile=profile)
        reports = banned_user.profile.user_reported_report.all()
        banned_user.save()
        for report in reports:
            banned_user.report_reason.add(report)
        
        # Send the email
        subject = 'Ban'
        message = 'You have been banned for the following reasons: []'
        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")
Art
  • 2,836
  • 4
  • 17
  • 34
Shadowwz
  • 57
  • 1
  • 7