@@ -2664,8 +2664,8 @@ def handle_csv_file(self, csv_file, *args, **kwargs):
2664
2664
2665
2665
def extract_info (row , field_name_list , default_response = "" ):
2666
2666
"""Pass a row, and a lowercase list of field names
2667
- extract the first match found (case insensitive ) and return the value from the row
2668
- empty string returned if the value is not found in the row"""
2667
+ extract the first match found (case insenstive ) and return the value from the row
2668
+ emptry string returned if the value is not found in the row"""
2669
2669
case_insensitive_row = {k .lower (): v for k , v in row .items ()}
2670
2670
for name in field_name_list :
2671
2671
try :
@@ -2674,13 +2674,14 @@ def extract_info(row, field_name_list, default_response=""):
2674
2674
pass
2675
2675
return default_response
2676
2676
2677
- def columns_exist ( field_names , columns ):
2677
+ def columns_exist_in_csv ( csv_reader , columns ):
2678
2678
"""returns True if any value in the list `columns` exists in the file"""
2679
- case_insensitive_row = {k .lower () for k in field_names }
2680
- for column in columns :
2681
- if column in case_insensitive_row :
2682
- return True
2683
- return False
2679
+ first_row = next (csv_reader )
2680
+ result = extract_info (first_row , columns , None )
2681
+ if result is None :
2682
+ return False
2683
+ else :
2684
+ return True
2684
2685
2685
2686
csv_file .seek (0 )
2686
2687
csv_reader = csv .DictReader (TextIOWrapper (csv_file .file ))
@@ -2695,131 +2696,67 @@ def columns_exist(field_names, columns):
2695
2696
error = ""
2696
2697
# order matters here - the most important columns should be validated last,
2697
2698
# so the error refers to the most important missing column
2698
- try :
2699
- if not columns_exist (csv_reader .fieldnames , phone_field_names ):
2700
- error = "Warning: This file does not contain a phone column"
2701
- else :
2702
- some_columns_exist = True
2703
- if not columns_exist (csv_reader .fieldnames , address_field_names ):
2704
- error = "Warning: This file does not contain an address column"
2705
- else :
2706
- some_columns_exist = True
2707
- if not columns_exist (csv_reader .fieldnames , name_field_names ):
2708
- error = "Warning: This file does not contain a name column"
2709
- else :
2710
- some_columns_exist = True
2711
- if not columns_exist (csv_reader .fieldnames , email_field_names ):
2712
- error = "Warning: This file does not contain an email column"
2713
- else :
2714
- some_columns_exist = True
2715
- if not some_columns_exist :
2716
- error = (
2717
- "Unable to read information from this CSV file. Make sure it contains an email and a name column"
2718
- )
2719
-
2720
- total_tos = 0
2721
- total_skipped = 0
2722
- for row in csv_reader :
2723
- bidder_number = extract_info (row , bidder_number_fields )
2724
- email = extract_info (row , email_field_names )
2725
- name = extract_info (row , name_field_names )
2726
- phone = extract_info (row , phone_field_names )
2727
- address = extract_info (row , address_field_names )
2728
- is_club_member = extract_info (row , is_club_member_fields )
2729
- if is_club_member .lower () in ["yes" , "true" , "member" , "club member" ]:
2730
- is_club_member = True
2699
+ if not columns_exist_in_csv (csv_reader , phone_field_names ):
2700
+ error = "This file does not contain a phone column"
2701
+ else :
2702
+ some_columns_exist = True
2703
+ if not columns_exist_in_csv (csv_reader , address_field_names ):
2704
+ error = "This file does not contain an address column"
2705
+ else :
2706
+ some_columns_exist = True
2707
+ if not columns_exist_in_csv (csv_reader , name_field_names ):
2708
+ error = "This file does not contain a name column"
2709
+ else :
2710
+ some_columns_exist = True
2711
+ if not columns_exist_in_csv (csv_reader , email_field_names ):
2712
+ error = "This file does not contain an email column"
2713
+ else :
2714
+ some_columns_exist = True
2715
+ if not some_columns_exist :
2716
+ error = "Unable to read information from this CSV file. Make sure it contains an email and name column"
2717
+ total_tos = 0
2718
+ total_skipped = 0
2719
+ initial_formset_data = []
2720
+ for row in csv_reader :
2721
+ bidder_number = extract_info (row , bidder_number_fields )
2722
+ email = extract_info (row , email_field_names )
2723
+ name = extract_info (row , name_field_names )
2724
+ phone = extract_info (row , phone_field_names )
2725
+ address = extract_info (row , address_field_names )
2726
+ is_club_member = extract_info (row , is_club_member_fields )
2727
+ if (email or name or phone or address ) and total_tos <= self .max_users_that_can_be_added_at_once :
2728
+ if self .tos_is_in_auction (self .auction , name , email ):
2729
+ total_skipped += 1
2731
2730
else :
2732
- is_club_member = False
2733
- if email or name or phone or address :
2734
- if self .tos_is_in_auction (self .auction , name , email ):
2735
- logger .debug ("CSV import skipping %s" , name )
2736
- total_skipped += 1
2737
- else :
2738
- logger .debug ("CSV import adding %s" , name )
2739
- if bidder_number :
2740
- if AuctionTOS .objects .filter (auction = self .auction , bidder_number = bidder_number ).first ():
2741
- bidder_number = ""
2742
- AuctionTOS .objects .create (
2743
- auction = self .auction ,
2744
- pickup_location = self .auction .location_qs .first (),
2745
- manually_added = True ,
2746
- bidder_number = bidder_number ,
2747
- name = name ,
2748
- phone_number = phone ,
2749
- email = email ,
2750
- address = address ,
2751
- is_club_member = is_club_member ,
2752
- )
2753
- total_tos += 1
2754
- if error :
2755
- messages .error (self .request , error )
2756
- msg = f"{ total_tos } users added"
2757
- if total_skipped :
2758
- msg += (
2759
- f", { total_skipped } users are already in this auction (matched by email, or name if email not set)"
2760
- )
2761
- messages .info (self .request , msg )
2762
- url = reverse ("auction_tos_list" , kwargs = {"slug" : self .auction .slug })
2763
- response = HttpResponse (status = 200 )
2764
- response ["HX-Redirect" ] = url
2765
- return response
2766
- except (UnicodeDecodeError , ValueError ) as e :
2731
+ total_tos += 1
2732
+ initial_formset_data .append (
2733
+ {
2734
+ "bidder_number" : bidder_number ,
2735
+ "name" : name ,
2736
+ "phone" : phone ,
2737
+ "email" : email ,
2738
+ "address" : address ,
2739
+ "is_club_member" : is_club_member ,
2740
+ }
2741
+ )
2742
+ # this needs to be added to the session in order to persist when moving from POST (this csv processing) to GET
2743
+ self .request .session ["initial_formset_data" ] = initial_formset_data
2744
+ if total_tos >= self .max_users_that_can_be_added_at_once :
2767
2745
messages .error (
2768
- self .request , f"Unable to read file. Make sure this is a valid UTF-8 CSV file. Error was: { e } "
2746
+ self .request ,
2747
+ f"You can only add { self .max_users_that_can_be_added_at_once } users at once; run this again to add additional users." ,
2769
2748
)
2770
- url = reverse ("bulk_add_users" , kwargs = {"slug" : self .auction .slug })
2771
- response = HttpResponse (status = 200 )
2772
- response ["HX-Redirect" ] = url
2773
- return response
2774
-
2775
- # The code below would populate the formset with the info from the CSV.
2776
- # This process is simply not working, and it fails silently with no log.
2777
-
2778
- # total_tos = 0
2779
- # total_skipped = 0
2780
- # initial_formset_data = []
2781
- # for row in csv_reader:
2782
- # bidder_number = extract_info(row, bidder_number_fields)
2783
- # email = extract_info(row, email_field_names)
2784
- # name = extract_info(row, name_field_names)
2785
- # phone = extract_info(row, phone_field_names)
2786
- # address = extract_info(row, address_field_names)
2787
- # is_club_member = extract_info(row, is_club_member_fields)
2788
-
2789
- # if (email or name or phone or address) and total_tos <= self.max_users_that_can_be_added_at_once:
2790
- # if self.tos_is_in_auction(self.auction, name, email):
2791
- # total_skipped += 1
2792
- # else:
2793
- # total_tos += 1
2794
- # initial_formset_data.append(
2795
- # {
2796
- # "bidder_number": bidder_number,
2797
- # "name": name,
2798
- # "phone_number": phone,
2799
- # "email": email,
2800
- # "address": address,
2801
- # "is_club_member": is_club_member,
2802
- # "pickup_location": "2",
2803
- # }
2804
- # )
2805
- # # this needs to be added to the session in order to persist when moving from POST (this csv processing) to GET
2806
- # self.request.session["initial_formset_data"] = initial_formset_data
2807
- # if total_tos >= self.max_users_that_can_be_added_at_once:
2808
- # messages.error(
2809
- # self.request,
2810
- # f"You can only add {self.max_users_that_can_be_added_at_once} users at once; run this again to add additional users.",
2811
- # )
2812
- # if total_skipped:
2813
- # messages.info(
2814
- # self.request,
2815
- # f"{total_skipped} users are already in this auction (matched by email, or name if email not set) and do not appear below",
2816
- # )
2817
- # if error:
2818
- # messages.error(self.request, error)
2819
- # if total_tos:
2820
- # self.extra_rows = total_tos
2821
- # # note that regardless of whether this is valid or not, we redirect to the same page after parsing the CSV file
2822
- # return redirect(reverse("bulk_add_users", kwargs={"slug": self.auction.slug}))
2749
+ if total_skipped :
2750
+ messages .info (
2751
+ self .request ,
2752
+ f"{ total_skipped } users are already in this auction (matched by email, or name if email not set) and do not appear below" ,
2753
+ )
2754
+ if error :
2755
+ messages .error (self .request , error )
2756
+ if total_tos :
2757
+ self .extra_rows = total_tos
2758
+ # note that regardless of whether this is valid or not, we redirect to the same page after parsing the CSV file
2759
+ return redirect (reverse ("bulk_add_users" , kwargs = {"slug" : self .auction .slug }))
2823
2760
2824
2761
def post (self , request , * args , ** kwargs ):
2825
2762
csv_file = request .FILES .get ("csv_file" , None )
@@ -2851,7 +2788,6 @@ def get_context_data(self, **kwargs):
2851
2788
context ["other_auctions" ] = (
2852
2789
Auction .objects .exclude (is_deleted = True )
2853
2790
.filter (Q (created_by = self .request .user ) | Q (auctiontos__user = self .request .user , auctiontos__is_admin = True ))
2854
- .exclude (pk = self .auction .pk )
2855
2791
.distinct ()
2856
2792
.order_by ("-date_posted" )[:10 ]
2857
2793
)
@@ -5760,15 +5696,13 @@ def unique_page_views(self, minutes, view_type="anon"):
5760
5696
timeframe = timezone .now () - timezone .timedelta (minutes = minutes )
5761
5697
base_qs = PageView .objects .filter (date_start__gte = timeframe )
5762
5698
if view_type == "logged_in" :
5763
- # return base_qs.filter(user__isnull=False).aggregate(unique_views=Count("user", distinct=True))[
5764
- # "unique_views"
5765
- # ]
5766
- return base_qs .filter (user__isnull = False ).values ("user" ).distinct ().count ()
5699
+ return base_qs .filter (user__isnull = False ).aggregate (unique_views = Count ("user" , distinct = True ))[
5700
+ "unique_views"
5701
+ ]
5767
5702
if view_type == "anon" :
5768
- # return base_qs.filter(user__isnull=True, session_id__isnull=False).aggregate(
5769
- # unique_views=Count("session_id", distinct=True)
5770
- # )["unique_views"]
5771
- return base_qs .filter (user__isnull = True , session_id__isnull = False ).values ("session_id" ).distinct ().count ()
5703
+ return base_qs .filter (user__isnull = True , session_id__isnull = False ).aggregate (
5704
+ unique_views = Count ("session_id" , distinct = True )
5705
+ )["unique_views" ]
5772
5706
5773
5707
def get_context_data (self , ** kwargs ):
5774
5708
context = super ().get_context_data (** kwargs )
0 commit comments